diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index d0aeadd..8ec7ec3 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -4248,14 +4248,24 @@ bool NativeCodeBasicBlock::LoadLoadOpStoreIndirectValue(InterCodeProcedure* proc return false; } - for (int i = 0; i < size; i++) { - mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins1->mSrc[0].mIntConst + i)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins1->mSrc[0].mTemp])); + if (rins1->mSrc[0].mIntConst == wins->mSrc[1].mIntConst && rins0->mSrc[0].mIntConst != wins->mSrc[1].mIntConst) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins0->mSrc[0].mIntConst + i)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins0->mSrc[0].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins0->mSrc[0].mIntConst + i)); - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins0->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins1->mSrc[0].mIntConst + i)); + mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins1->mSrc[0].mTemp])); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins1->mSrc[0].mIntConst + i)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins1->mSrc[0].mTemp])); + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins0->mSrc[0].mIntConst + i)); + mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins0->mSrc[0].mTemp])); + } mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, wins->mSrc[1].mIntConst + i)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp])); @@ -9968,7 +9978,7 @@ bool NativeCodeBasicBlock::FindImmediateStore(int at, int reg, const NativeCodeI return false; } -bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains) +bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains, int cycles) { if (!mPatched) { @@ -9993,21 +10003,36 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ { if (ins.ChangesAddress()) return false; - return !(ins.mLive & LIVE_MEM); + if (!HasAsmInstructionMode(ins.mType, ains.mMode)) + return false; + if (ins.mLive & LIVE_MEM) + { + cycles--; + if (cycles == 0) + return false; + } + else + return true; } else return true; } else if (ins.mType == ASMIT_JSR) { - if (ins.mFlags & NCIF_RUNTIME) + if (ains.mMode == ASMIM_ABSOLUTE_X || ains.mMode == ASMIM_ABSOLUTE_Y) + return false; + else if (ins.mFlags & NCIF_RUNTIME) { if (ins.UsesZeroPage(reg)) return false; } else - return false; + return false; } + else if (ains.mMode == ASMIM_ABSOLUTE_X && ins.ChangesXReg()) + return false; + else if (ains.mMode == ASMIM_ABSOLUTE_Y && ins.ChangesYReg()) + return false; else if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress + 1 == reg)) return false; else if (ins.ChangesZeroPage(reg)) @@ -10018,9 +10043,9 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ at++; } - if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(reg, 0, ains)) + if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(reg, 0, ains, cycles)) return false; - if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(reg, 0, ains)) + if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(reg, 0, ains, cycles)) return false; } @@ -10046,9 +10071,9 @@ bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const Nativ { if (ins.UsesAddress()) { - assert(!(ins.mLive & LIVE_MEM)); ins.CopyMode(ains); - return true; + if (!(ins.mLive & LIVE_MEM)) + return true; } return false; @@ -15940,6 +15965,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_CMP && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 2].mAddress && + !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_MEM))) + { + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_CMP; mIns[i + 1].mLive |= LIVE_CPU_REG_Z; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } + #if 1 if ( @@ -16747,11 +16784,11 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass if (i + 1 < mIns.Size()) { if ( - mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE && + mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X || mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y) && 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])) + if (CheckSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i], 3)) { proc->ResetPatched(); if (PatchSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i])) @@ -16898,6 +16935,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } } + + if ( + mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && + mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 3].mType == ASMIT_LDY && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress != mIns[i + 0].mAddress && + mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 4].mLive & LIVE_CPU_REG_Y)) + { + int j = i + 5; + while (j < mIns.Size() && !mIns[j].ChangesYReg()) + j++; + if (j < mIns.Size() && mIns[j].mType == ASMIT_LDY && mIns[j].mMode == ASMIM_IMMEDIATE && mIns[j].mAddress == mIns[i + 0].mAddress) + { + int reg = mIns[1].mAddress; mIns[1].mAddress = mIns[4].mAddress; mIns[4].mAddress = reg; + int yr = mIns[0].mAddress; mIns[0].mAddress = mIns[3].mAddress; mIns[3].mAddress = yr; + mIns[1].mLive |= LIVE_MEM; + mIns[4].mLive |= LIVE_MEM; + progress = true; + } + } #endif } diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 55d78dd..3a0909b 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -279,7 +279,7 @@ 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 CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains, int cycles); bool PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains); bool CheckForwardSumYPointer(int reg, int base, int index, int at, int yval); diff --git a/samples/games/hscrollshmup.c b/samples/games/hscrollshmup.c index fa207aa..ccbb1e7 100644 --- a/samples/games/hscrollshmup.c +++ b/samples/games/hscrollshmup.c @@ -31,8 +31,10 @@ char spriteset[4096] = { char xtileset[16][64]; char xtilemap[144 * 5]; char stars[24]; +char xcollision[256]; #pragma align(xtileset, 64); +#pragma align(xcollision, 256) void tiles_unpack(void) { @@ -49,6 +51,12 @@ void tiles_unpack(void) xtilemap[y * 144 + x] = tilemap[y * 128 + (x & 127)]; } } + + for(char i=0; i<160; i+=40) + { + for(char j=0; j<3; j++) + xcollision[i + j] = 1; + } } void tiles_draw0(char * dp, char * tm) @@ -343,6 +351,7 @@ struct Enemy int px; byte py; sbyte dx; + byte state, pad0, pad1, pad2; } enemies[5]; int spx = 40; @@ -357,18 +366,36 @@ void enemies_move(void) { for(char i=0; i<5; i++) { - if (enemies[i].dx) + if (enemies[i].state) { enemies[i].px += enemies[i].dx; int rx = enemies[i].px - spx; if (rx < -192 || rx >= 480) { - enemies[i].dx = 0; + enemies[i].state = 0; ecount--; + spr_show(2 + i, false); } + else + { + spr_move(2 + i, rx + 24, enemies[i].py + 50); - spr_move(2 + i, rx + 24, enemies[i].py + 50); + if (enemies[i].state & 0x80) + { + + } + else + { + spr_image(2 + i, 127 - (enemies[i].state >> 2)); + enemies[i].state--; + if (enemies[i].state == 0) + { + spr_show(2 + i, false); + ecount--; + } + } + } } } } @@ -382,9 +409,10 @@ void enemies_spawn(void) __assume(e < 5); sbyte v = 1 + (u & 3); - enemies[ecount].py = 20 + 30 * e; + enemies[ecount].py = 21 + 32 * e; enemies[ecount].dx = vpx < 0 ? v : -v; enemies[ecount].px = (vpx < 0 ? spx - 56 : spx + 320) + ((u >> 1) & 31); + enemies[ecount].state = 0x80; int rx = enemies[ecount].px - spx; @@ -392,6 +420,43 @@ void enemies_spawn(void) ecount++; } +void shots_check(void) +{ + Shot * ps = shots; + + for(char i=0; i<5; i++) + { + if (enemies[i].state & 0x80) + { + sbyte rx = (enemies[i].px - spx) >> 3; + if (rx >= 0 && rx < 40) + { + Shot * ss = ps->next; + while (ss->ty < i) + { + ps = ss; + ss = ps->next; + } + + while (ss->ty == i) + { + if (xcollision[(char)(ss->x - rx)]) + { + ps->next = ss->next; + ss->next = freeShot; + freeShot = ss; + enemies[i].state = 64; + break; + } + + ps = ss; + ss = ps->next; + } + } + } + } +} + int main(void) { cia_init(); @@ -498,15 +563,19 @@ int main(void) spr_move(0, 172 - 4 * vpx, 50 + spy); spr_move(7, 180 - 4 * vpx, 58 + spy); - vic.color_border++; - vic_waitLine(82); - vic.color_border++; + vic.color_border = VCOL_BLACK; + vic_waitTop(); + while (vic.raster < 82) + ; + + vic.color_border = VCOL_BLUE; tiles_draw(spx & 4095); - vic.color_border--; + vic.color_border = VCOL_WHITE; + if (edelay) { edelay--; - if (edelay < 5) + if (edelay < 10 && !(edelay & 1)) enemies_spawn(); } else @@ -515,7 +584,8 @@ int main(void) if (!ecount) edelay = 64 + (rand() & 63); } - vic.color_border--; + + shots_check(); spx += vpx >> 2; }