diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 0cf6149..9ca98cf 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -114,6 +114,9 @@ rem @echo off @call :test structmembertest.c @if %errorlevel% neq 0 goto :error +@call :test structarraycopy.c +@if %errorlevel% neq 0 goto :error + @call :test randsumtest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/structarraycopy.c b/autotest/structarraycopy.c new file mode 100644 index 0000000..6965d3c --- /dev/null +++ b/autotest/structarraycopy.c @@ -0,0 +1,49 @@ + + +struct Point +{ + int x, y; +}; + + +Point tcorners[8], pcorners[8]; + +int bm_line(void) +{ + +} + +void drawCube(void) +{ + for(char i=0; i<8; i++) + { + if (!(i & 1)) + bm_line(); + if (!(i & 2)) + bm_line(); + if (!(i & 4)) + bm_line(); + + pcorners[i] = tcorners[i]; + } +} + +int main(void) +{ + for(int i=0; i<8; i++) + { + tcorners[i].x = (i + 1) * 3; + tcorners[i].y = (i + 1) * 7; + } + + drawCube(); + + int sum = 0; + for(int i=0; i<8; i++) + { + sum += pcorners[i].x; + sum -= tcorners[i].y; + } + + return sum + 144; +} \ No newline at end of file diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 147d134..6c5d7cb 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -10,6 +10,8 @@ static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 0x00000020; static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 0x00000040; static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080; +static const uint64 COPT_OPTIMIZE_CODE_SIZE = 0x00000100; + static const uint64 COPT_TARGET_PRG = 0x100000000ULL; static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL; static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL; @@ -24,7 +26,7 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; -static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; +static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE; static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index e08eca0..ec496b5 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -690,6 +690,42 @@ bool NativeCodeInstruction::UsesZeroPage(int address) const return true; else if (mMode == ASMIM_INDIRECT_Y && (mAddress == address || mAddress + 1 == address)) return true; + else if (mType == ASMIT_JSR) + { + if (address >= BC_REG_ACCU && address < BC_REG_ACCU + 4) + return true; + if (address >= BC_REG_WORK && address < BC_REG_WORK + 4) + return true; + + if (mFlags & NCIF_RUNTIME) + { + + if (mFlags & NCIF_USE_ZP_32_X) + { + if (address >= mParam && address < mParam + 4) + return true; + } + + if (mFlags & NCIF_FEXEC) + { + if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END) + return true; + } + } + else + { + if (mLinkerObject) + { + for (int i = 0; i < mLinkerObject->mNumTemporaries; i++) + { + if (address >= mLinkerObject->mTemporaries[i] && address < mLinkerObject->mTemporaries[i] + mLinkerObject->mTempSizes[i]) + return true; + } + } + } + + return false; + } else return false; } @@ -778,6 +814,20 @@ bool NativeCodeInstruction::ChangesAccu(void) const +bool NativeCodeInstruction::UsesAddress(void) const +{ + if (mMode != ASMIM_IMPLIED) + { + return + mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || + mType == ASMIT_LDA || mType == ASMIT_LDX || mType == ASMIT_LDY || + mType == ASMIT_CMP || mType == ASMIT_CPX || mType == ASMIT_CPY || + mType == ASMIT_ADC || mType == ASMIT_SBC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR; + } + else + return false; +} + bool NativeCodeInstruction::ChangesAddress(void) const { if (mMode != ASMIM_IMPLIED) @@ -4897,7 +4947,14 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; int size = ins->mConst.mOperandSize; - if (size < 4) + int msize = 4; + + if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) + msize = 8; + else if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) + msize = 2; + + if (size <= msize) { for (int i = 0; i < size; i++) { @@ -9559,6 +9616,33 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc) pblock->mIns.Push(mIns[0]); mIns.Remove(0); + changed = true; + } + } + else if (mIns[0].mType == ASMIT_LDX && mIns[0].mMode == ASMIM_ZERO_PAGE && !(mIns[0].mLive & LIVE_CPU_REG_A)) + { + if (lblock->mIns[ls - 2].mType == ASMIT_LDA && lblock->mIns[ls - 2].mMode == ASMIM_ZERO_PAGE && lblock->mIns[ls - 2].mAddress == mIns[0].mAddress && + lblock->mIns[ls - 1].mType == ASMIT_CMP && !(lblock->mIns[ls - 1].mLive & LIVE_CPU_REG_A)) + { + lblock->mIns[ls - 2].mType = ASMIT_LDX; lblock->mIns[ls - 2].mLive |= LIVE_CPU_REG_X; + lblock->mIns[ls - 1].mType = ASMIT_CPX; lblock->mIns[ls - 1].mLive |= LIVE_CPU_REG_X; + + pblock->mIns.Push(mIns[0]); + mIns.Remove(0); + + changed = true; + } + } + else if (mIns[0].mType == ASMIT_LDA && mIns[0].mMode == ASMIM_ZERO_PAGE) + { + if (lblock->mIns[ls - 2].mType == ASMIT_LDA && lblock->mIns[ls - 2].mMode == ASMIM_ZERO_PAGE && lblock->mIns[ls - 2].mAddress == mIns[0].mAddress && + lblock->mIns[ls - 1].mType == ASMIT_CMP) + { + pblock->mIns.Push(mIns[0]); + mIns.Remove(0); + + lblock->mIns[ls - 1].mLive |= LIVE_CPU_REG_A; + changed = true; } } @@ -9737,6 +9821,103 @@ bool NativeCodeBasicBlock::FindImmediateStore(int at, int reg, const NativeCodeI return false; } +bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains) +{ + if (!mPatched) + { + mPatched = true; + + if (at == 0) + { + if (!mEntryRequiredRegs[reg]) + return true; + + if (mNumEntries > 1) + return false; + } + + while (at < mIns.Size()) + { + NativeCodeInstruction& ins(mIns[at]); + + if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg) + { + if (ins.UsesAddress()) + { + if (ins.ChangesAddress()) + return false; + return !(ins.mLive & LIVE_MEM); + } + else + return true; + } + else if (ins.mType == ASMIT_JSR) + { + if (ins.mFlags & NCIF_RUNTIME) + { + if (ins.UsesZeroPage(reg)) + return false; + } + else + return false; + } + else if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress + 1 == reg)) + return false; + else if (ins.ChangesZeroPage(reg)) + return true; + else if (ains.MayBeChangedOnAddress(ins)) + return false; + + at++; + } + + if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(reg, 0, ains)) + return false; + if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(reg, 0, ains)) + return false; + } + + return true; +} + +bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains) +{ + bool changed = false; + + if (!mPatched) + { + mPatched = true; + + if (at == 0 && !mEntryRequiredRegs[reg]) + return false; + + while (at < mIns.Size()) + { + NativeCodeInstruction& ins(mIns[at]); + + if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg) + { + if (ins.UsesAddress()) + { + assert(!(ins.mLive & LIVE_MEM)); + ins.CopyMode(ains); + return true; + } + + return false; + } + + at++; + } + + if (mTrueJump && mTrueJump->PatchSingleUseGlobalLoad(reg, 0, ains)) + changed = true; + if (mFalseJump && mFalseJump->PatchSingleUseGlobalLoad(reg, 0, ains)) + changed = true; + } + + return changed; +} bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yval) { @@ -9744,6 +9925,15 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv { mPatched = true; + if (at == 0) + { + if (!mEntryRequiredRegs[reg] && !mEntryRequiredRegs[reg + 1]) + return true; + + if (mNumEntries > 1) + yval = -1; + } + while (at < mIns.Size()) { NativeCodeInstruction& ins(mIns[at]); @@ -9764,6 +9954,12 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv yval = (yval + 1) & 255; else if (ins.mType == ASMIT_DEY && yval >= 0) yval = (yval - 1) & 255; + else if (ins.mType == ASMIT_JSR) + { + if (ins.UsesZeroPage(reg) || ins.UsesZeroPage(reg + 1)) + return false; + yval = -1; + } else if (ins.ChangesYReg()) yval = -1; @@ -9786,6 +9982,8 @@ bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(int reg, int at, int yv if (!mPatched) { mPatched = true; + if (at == 0 && !mEntryRequiredRegs[reg] && !mEntryRequiredRegs[reg + 1]) + return false; while (at < mIns.Size()) { @@ -10838,6 +11036,10 @@ bool NativeCodeBasicBlock::MoveLoadStoreOutOfXYRangeUp(int at) return false; if (mIns[j].ChangesAddress() && mIns[j].SameEffectiveAddress(mIns[at + 1])) return false; + if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_X && mIns[j].ChangesXReg()) + return false; + if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg()) + return false; if (mIns[j].mType == ASMIT_LDA) { @@ -10973,32 +11175,54 @@ bool NativeCodeBasicBlock::MoveStoreXUp(int at) { bool done = false; + int n = 0, inc = 0;; + int reg = mIns[at].mAddress; + while (at > 0) { - if (mIns[at - 1].ChangesXReg() || mIns[at - 1].mType == ASMIT_STX) - return done; - if (mIns[at].mMode == ASMIM_ZERO_PAGE) + if (mIns[at - 1].mType == ASMIT_INX) { - if ((mIns[at - 1].mMode == ASMIM_ZERO_PAGE || mIns[at - 1].mMode == ASMIM_INDIRECT_Y) && mIns[at - 1].mAddress == mIns[at].mAddress) - return done; - if (mIns[at - 1].mMode == ASMIM_INDIRECT_Y && mIns[at - 1].mAddress + 1 == mIns[at].mAddress) - return done; + n++; + inc++; + } + else if (mIns[at - 1].mType == ASMIT_DEX) + { + n++; + inc--; } else { - if (mIns[at - 1].mMode == ASMIM_ABSOLUTE && mIns[at - 1].mLinkerObject == mIns[at].mLinkerObject && mIns[at - 1].mAddress == mIns[at].mAddress) + if (mIns[at - 1].mType == ASMIT_LDX || mIns[at - 1].mType == ASMIT_TAX) return done; - else if ((mIns[at - 1].mMode == ASMIM_ABSOLUTE_X || mIns[at - 1].mMode == ASMIM_ABSOLUTE_Y) && mIns[at - 1].mLinkerObject == mIns[at].mLinkerObject) + else if (mIns[at - 1].ChangesXReg() || mIns[at - 1].mType == ASMIT_STX) return done; + else if (mIns[at + n].mMode == ASMIM_ZERO_PAGE) + { + if ((mIns[at - 1].mMode == ASMIM_ZERO_PAGE || mIns[at - 1].mMode == ASMIM_INDIRECT_Y) && mIns[at - 1].mAddress == reg) + return done; + if (mIns[at - 1].mMode == ASMIM_INDIRECT_Y && mIns[at - 1].mAddress + 1 == reg) + return done; + } + else + { + if (mIns[at - 1].mMode == ASMIM_ABSOLUTE && mIns[at - 1].mLinkerObject == mIns[at + n].mLinkerObject && mIns[at - 1].mAddress == mIns[at + n].mAddress) + return done; + else if ((mIns[at - 1].mMode == ASMIM_ABSOLUTE_X || mIns[at - 1].mMode == ASMIM_ABSOLUTE_Y) && mIns[at - 1].mLinkerObject == mIns[at + n].mLinkerObject) + return done; + } + + mIns[at].mLive |= mIns[at - 1].mLive; + + NativeCodeInstruction ins = mIns[at - 1]; + if (ins.mMode == ASMIM_ABSOLUTE_X) + ins.mAddress -= inc; + + for (int i = 0; i <= n; i++) + mIns[at - 1 + i] = mIns[at + i]; + mIns[at + n] = ins; + done = true; } - - mIns[at].mLive |= mIns[at - 1].mLive; - - NativeCodeInstruction ins = mIns[at - 1]; - mIns[at - 1] = mIns[at]; - mIns[at] = ins; at--; - done = true; } return done; @@ -13857,8 +14081,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #if 1 for (int i = 0; i + 2 < mIns.Size(); i++) { - if ((mIns[i + 0].mType == ASMIT_TAX || mIns[i + 0].mType == ASMIT_TAY) && - mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && + if (mIns[i + 0].mType == ASMIT_TAX && + mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A))) + { + if (MoveLoadStoreOutOfXYRangeUp(i)) + changed = true; + } + else if ( + mIns[i + 0].mType == ASMIT_TAY && + mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A))) { if (MoveLoadStoreOutOfXYRangeUp(i)) @@ -15790,6 +16022,41 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } #endif + else if ( + mIns[i + 0].mType == ASMIT_TXA && + mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 && + mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C)) + { + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_INX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X; + if (mIns[i + 2].mAddress == 2) + mIns[i + 2].mType = ASMIT_INX; + else + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X; + if (mIns[i + 3].mLive & LIVE_CPU_REG_A) + mIns[i + 3].mType = ASMIT_TXA; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_TXA && + mIns[i + 1].mType == ASMIT_SEC && + mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 && + mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C)) + { + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X; + if (mIns[i + 2].mAddress == 2) + mIns[i + 2].mType = ASMIT_DEX; + else + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X; + if (mIns[i + 3].mLive & LIVE_CPU_REG_A) + mIns[i + 3].mType = ASMIT_TXA; + progress = true; + } + else if ( mIns[i + 0].mType == ASMIT_TYA && mIns[i + 1].mType == ASMIT_CLC && @@ -16183,6 +16450,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass } } #endif + if (i + 1 < mIns.Size()) + { + if ( + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE && + mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) + { + proc->ResetPatched(); + if (CheckSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i])) + { + proc->ResetPatched(); + if (PatchSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i])) + progress = true; + } + } + } + if (i + 5 < mIns.Size()) { if ( @@ -16221,7 +16504,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED; proc->ResetPatched(); - progress = PatchGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress); + if (PatchGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress)) + progress = true; } } #endif diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 41ba416..07471fa 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -84,6 +84,7 @@ public: bool LoadsAccu(void) const; bool ChangesAccuAndFlag(void) const; bool ChangesAddress(void) const; + bool UsesAddress(void) const; bool ChangesAccu(void) const; bool UsesAccu(void) const; bool ChangesCarry(void) const; @@ -273,6 +274,9 @@ public: bool CheckGlobalAddressSumYPointer(int reg, int at, int yval); bool PatchGlobalAddressSumYPointer(int reg, int at, int yval, LinkerObject * lobj, int address); + + bool CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains); + bool PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains); }; class NativeCodeProcedure diff --git a/samples/games/hscrollshmup.c b/samples/games/hscrollshmup.c index 0074819..2ef99c4 100644 --- a/samples/games/hscrollshmup.c +++ b/samples/games/hscrollshmup.c @@ -330,59 +330,53 @@ struct Enemy int px; byte py; sbyte dx; - byte n; } enemies[5]; - int spx = 40; - int vpx = 16; - int ax = 0; - char spy = 100; - char fdelay = 0; +int spx = 40; +int vpx = 16; +int ax = 0; +char spy = 100; +char fdelay = 0; +char edelay = 5; +char ecount = 0; void enemies_move(void) { - bool elive = false; - for(char i=0; i<5; i++) { - if (enemies[i].n) + if (enemies[i].dx) { - enemies[i].n--; enemies[i].px += enemies[i].dx; int rx = enemies[i].px - spx; - if (enemies[i].dx < 0) + if (rx < -192 || rx >= 480) { - if (rx < -24) - enemies[i].n = 0; - } - else - { - if (rx > 320) - enemies[i].n = 0; + enemies[i].dx = 0; + ecount--; } spr_move(2 + i, rx + 24, enemies[i].py + 50); - - elive = true; } } +} - if (!elive) - { - for(char i=0; i<5; i++) - { - sbyte v = 4 + (rand() & 1); - enemies[i].py = 20 + 30 * i; - enemies[i].dx = vpx < 0 ? v : -v; - enemies[i].px = (vpx < 0 ? spx - 56 : spx + 320) + (rand() & 31); - enemies[i].n = 100; +void enemies_spwan(void) +{ + char u = rand(); - int rx = enemies[i].px - spx; + char e = ecount; - spr_set(2 + i, true, rx + 24, enemies[i].py + 50, 96, VCOL_YELLOW, true, false, false); - } - } + __assume(e < 5); + + sbyte v = 1 + (u & 3); + enemies[ecount].py = 20 + 30 * e; + enemies[ecount].dx = vpx < 0 ? v : -v; + enemies[ecount].px = (vpx < 0 ? spx - 56 : spx + 320) + ((u >> 1) & 31); + + int rx = enemies[ecount].px - spx; + + spr_set(2 + ecount, true, rx + 24, enemies[ecount].py + 50, vpx < 0 ? 97 : 96, VCOL_YELLOW, true, false, false); + ecount++; } int main(void) @@ -430,7 +424,7 @@ int main(void) spr_set(0, true, 160, 100, 64, VCOL_BLUE, true, false, false); spr_set(7, true, 160, 100, 64 + 16, VCOL_MED_GREY, true, false, false); - vic.spr_priority = 2; + vic.spr_priority = 0x80; vpx = 2; for(;;) @@ -497,15 +491,23 @@ int main(void) vic.color_border++; vic_waitLine(82); vic.color_border++; - tiles_draw(spx); + tiles_draw(spx & 4095); vic.color_border--; - enemies_move(); + if (edelay) + { + edelay--; + if (edelay < 5) + enemies_spwan(); + } + else + { + enemies_move(); + if (!ecount) + edelay = 64 + (rand() & 63); + } vic.color_border--; - spx += vpx >> 1; - - - spx &= 4095; + spx += vpx >> 2; } return 0;