From 6bd3ecb689393f761d03d259ee3244608f5d33e3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 19 Feb 2022 12:16:33 +0100 Subject: [PATCH] Fix over eager const expression inliner --- oscar64/Compiler.cpp | 1 + oscar64/Declaration.cpp | 2 +- oscar64/Declaration.h | 2 +- oscar64/Disassembler.cpp | 2 +- oscar64/GlobalAnalyzer.cpp | 4 + oscar64/InterCode.cpp | 5 +- oscar64/InterCodeGenerator.cpp | 5 + oscar64/NativeCodeGenerator.cpp | 454 +++++++++++++++++++++++++++----- oscar64/NativeCodeGenerator.h | 1 + oscar64/Parser.cpp | 10 + samples/games/hscrollshmup.c | 180 ++++++++++--- samples/memmap/easyflash.crt | Bin 114976 -> 114976 bytes 12 files changed, 558 insertions(+), 108 deletions(-) diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 3b0a8a7..86df25c 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -187,6 +187,7 @@ bool Compiler::GenerateCode(void) mGlobalAnalyzer->AnalyzeGlobalVariable(dec); } mGlobalAnalyzer->AutoInline(); + //mGlobalAnalyzer->DumpCallGraph(); mInterCodeGenerator->mCompilerOptions = mCompilerOptions; mNativeCodeGenerator->mCompilerOptions = mCompilerOptions; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 8e992eb..f26bbdf 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -484,7 +484,7 @@ Expression* Expression::ConstantFold(Errors * errors) Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), - mInteger(0), mNumber(0) + mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL) {} Declaration::~Declaration(void) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 2d4ebd0..882a8f9 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -176,7 +176,7 @@ public: Expression* mValue; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment; - int64 mInteger; + int64 mInteger, mMinValue, mMaxValue; double mNumber; uint64 mFlags; const Ident * mIdent; diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index cdf8766..14f50e3 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -645,7 +645,7 @@ void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int ban for (int i = 0; i < n; i++) { int k = memory[ip + i]; - if (k >= 32 && k < 128) + if (k >= 32 && k < 127) fprintf(file, "%c", k); else fprintf(file, "."); diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 1bba52c..6721eed 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -262,6 +262,10 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) { RegisterProc(Analyze(exp->mDecValue->mValue, procDec)); } + else if (exp->mDecValue->mType == DT_CONST_ADDRESS) + { + procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + } else if (exp->mDecValue->mType == DT_CONST_ASSEMBLER) { AnalyzeAssembler(exp->mDecValue->mValue, procDec); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 16e568e..73b4935 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4181,6 +4181,9 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) switch (ins->mCode) { + case IC_LOAD: + vr = ins->mDst.mRange; + break; case IC_CONSTANT: vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND; vr.mMinValue = vr.mMaxValue = ins->mConst.mIntConst; @@ -9404,7 +9407,7 @@ void InterCodeProcedure::Disassemble(FILE* file) void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) { -#if 1 +#if 0 #ifdef _WIN32 FILE* file; static bool initial = true; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 491a04d..de0ba69 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -49,6 +49,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* ins->mDst.mType = v.mReference == 1 ? InterTypeOf(v.mType) : IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mSrc[0].mOperandSize = v.mReference == 1 ? v.mType->mSize : 2; + if (v.mReference == 1 && v.mType->mType == DT_TYPE_ENUM) + { + ins->mDst.mRange.LimitMin(v.mType->mMinValue); + ins->mDst.mRange.LimitMax(v.mType->mMaxValue); + } if (v.mType->mFlags & DTF_VOLATILE) ins->mVolatile = true; block->Append(ins); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 0503cbc..934e1c6 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -6961,100 +6961,152 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p if (ins->mSrc[0].mTemp < 0) { int shift = ins->mSrc[0].mIntConst & 15; - if (shift == 0) + + if (ins->mSrc[1].IsUByte()) { - if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + if (shift == 0) + { + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (shift == 7) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + } + else if (shift == 6) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 3)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } - } - else if (shift == 7) - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); - } - else if (shift == 6) - { - int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; - if (sreg != treg) + else if (shift >= 8) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); - - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); - - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } else { - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + for (int i = 0; i < shift; i++) + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } } - else if (shift >= 8) - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - for (int i = 8; i < shift; i++) - mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> (shift - 8))); - mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> (shift - 8))); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); - } else { - if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + if (shift == 0) + { + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (shift == 7) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else if (shift == 6) + { + int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; + if (sreg != treg) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); + + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (shift >= 8) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + for (int i = 8; i < shift; i++) + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> (shift - 8))); + mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> (shift - 8))); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } else { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); - } + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + } - for (int i = 0; i < shift; i++) - { - mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg)); - } + for (int i = 0; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg)); + } - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift)); - mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift)); + mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } } else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff)) @@ -9011,6 +9063,27 @@ bool NativeCodeBasicBlock::LocalRegisterXYMap(void) for (int i = 0; i < mIns.Size(); i++) { + if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && (mIns[i].mMode != ASMIM_ZERO_PAGE || (xregs[mIns[i].mAddress] < 0 && xregs[mIns[i].mAddress] < 0) || (mIns[i + 1].mLive & LIVE_MEM))) + { + if (mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE) + { + if (xregs[mIns[i + 1].mAddress] >= 0 && !(mIns[i + 1].mLive & LIVE_MEM)) + { + int addr = mIns[i + 1].mAddress; + mIns[i + 1].CopyMode(mIns[i]); + mIns[i].mMode = ASMIM_ZERO_PAGE; + mIns[i].mAddress = addr; + } + else if (yregs[mIns[i + 1].mAddress] >= 0 && !(mIns[i + 1].mLive & LIVE_MEM)) + { + int addr = mIns[i + 1].mAddress; + mIns[i + 1].CopyMode(mIns[i]); + mIns[i].mMode = ASMIM_ZERO_PAGE; + mIns[i].mAddress = addr; + } + } + } + const NativeCodeInstruction& ins(mIns[i]); if (ins.ChangesXReg()) @@ -9437,6 +9510,61 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(void) } } } +#endif +#if 1 + if (mTrueJump && mTrueJump->mNumEntries == 1 && mFalseJump && mFalseJump->mNumEntries == 1) + { + int s = mIns.Size(); + if (s > 0 && mIns[s - 1].mType == ASMIT_CMP && mIns[s - 1].mMode == ASMIM_IMMEDIATE && !(mIns[s - 1].mLive & LIVE_CPU_REG_X)) + { + while (mTrueJump->mIns.Size() > 1 && mFalseJump->mIns.Size() > 1 && + + ((mTrueJump->mIns[0].mType == ASMIT_LDA && mTrueJump->mIns[1].mType == ASMIT_STA && !(mTrueJump->mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) || + (mTrueJump->mIns[0].mType == ASMIT_LDX && mTrueJump->mIns[1].mType == ASMIT_STX && !(mTrueJump->mIns[1].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)))) && + ((mFalseJump->mIns[0].mType == ASMIT_LDA && mFalseJump->mIns[1].mType == ASMIT_STA && !(mFalseJump->mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) || + (mFalseJump->mIns[0].mType == ASMIT_LDX && mFalseJump->mIns[1].mType == ASMIT_STX && !(mFalseJump->mIns[1].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)))) && + mTrueJump->mIns[0].SameEffectiveAddress(mFalseJump->mIns[0]) && mTrueJump->mIns[1].SameEffectiveAddress(mFalseJump->mIns[1]) && + HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode)) + { + mTrueJump->mIns[0].mType = ASMIT_LDX; + mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X; + mTrueJump->mIns[1].mType = ASMIT_STX; + + mIns.Insert(s - 1, mTrueJump->mIns[0]); + mIns.Insert(s, mTrueJump->mIns[1]); + s += 2; + mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); + mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); + + changed = true; + } + } + else if (s > 0 && mIns[s - 1].mType == ASMIT_LDA && !(mIns[s - 1].mLive & LIVE_CPU_REG_X)) + { + while (mTrueJump->mIns.Size() > 1 && mFalseJump->mIns.Size() > 1 && + + ((mTrueJump->mIns[0].mType == ASMIT_LDA && mTrueJump->mIns[1].mType == ASMIT_STA && !(mTrueJump->mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) || + (mTrueJump->mIns[0].mType == ASMIT_LDX && mTrueJump->mIns[1].mType == ASMIT_STX && !(mTrueJump->mIns[1].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)))) && + ((mFalseJump->mIns[0].mType == ASMIT_LDA && mFalseJump->mIns[1].mType == ASMIT_STA && !(mFalseJump->mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) || + (mFalseJump->mIns[0].mType == ASMIT_LDX && mFalseJump->mIns[1].mType == ASMIT_STX && !(mFalseJump->mIns[1].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)))) && + mTrueJump->mIns[0].SameEffectiveAddress(mFalseJump->mIns[0]) && mTrueJump->mIns[1].SameEffectiveAddress(mFalseJump->mIns[1]) && + HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode) && + !mIns[s - 1].MayBeChangedOnAddress(mTrueJump->mIns[1])) + { + mTrueJump->mIns[0].mType = ASMIT_LDX; + mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X; + mTrueJump->mIns[1].mType = ASMIT_STX; + + mIns.Insert(s - 1, mTrueJump->mIns[0]); + mIns.Insert(s, mTrueJump->mIns[1]); + s += 2; + mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); + mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); + + changed = true; + } + } + } #endif if (mTrueJump && mTrueJump->JoinTailCodeSequences()) changed = true; @@ -10179,6 +10307,121 @@ bool NativeCodeBasicBlock::FindDirectAddressSumY(int at, int reg, int& apos, int return false; } +bool NativeCodeBasicBlock::FindExternAddressSumY(int at, int reg, int& breg, int& ireg) +{ + int j = at - 7; + while (j >= 0) + { + if ( + mIns[j + 0].mType == ASMIT_CLC && + mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE && + mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && + mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg && + mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_ZERO_PAGE && mIns[j + 4].mAddress == mIns[j + 1].mAddress + 1 && + mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 && + mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1) + { + breg = mIns[j + 1].mAddress; + ireg = mIns[j + 2].mAddress; + + if (ireg == breg || reg == breg || ireg == reg) + return false; + + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1 || mIns[k].mAddress == ireg) && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } + else if ( + mIns[j + 0].mType == ASMIT_CLC && + mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE && + mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && + mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg && + mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_ZERO_PAGE && mIns[j + 4].mAddress == mIns[j + 2].mAddress + 1 && + mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 && + mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1) + { + breg = mIns[j + 2].mAddress; + ireg = mIns[j + 1].mAddress; + + if (ireg == breg || reg == breg || ireg == reg) + return false; + + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1 || mIns[k].mAddress == ireg) && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } + else if ( + mIns[j + 0].mType == ASMIT_STA && mIns[j + 0].mMode == ASMIM_ZERO_PAGE && + mIns[j + 1].mType == ASMIT_CLC && + mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && + mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg && + mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_ZERO_PAGE && mIns[j + 4].mAddress == mIns[j + 2].mAddress + 1 && + mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 && + mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1) + { + breg = mIns[j + 2].mAddress; + ireg = mIns[j + 0].mAddress; + + if (ireg == breg || reg == breg || ireg == reg) + return false; + + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1 || mIns[k].mAddress == ireg) && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } + + if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress()) + return false; + + j--; + } + + if (mFromJump) + { + while (j >= -6) + { + if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress()) + return false; + j--; + } + + if (mFromJump->FindExternAddressSumY(mFromJump->mIns.Size(), reg, breg, ireg)) + { + int k = 0; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1 || mIns[k].mAddress == ireg) && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } + } + + + return false; + +} + bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg) { int j = at - 7; @@ -10984,6 +11227,18 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc { bool changed = false; + + if (mIns.Size() == 2 && (mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE) && mIns[0].mType == ASMIT_LDA && mIns[1].mType == ASMIT_CMP && !(mIns[1].mFlags & NCIF_VOLATILE) && !(mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + if (!prevBlock) + return OptimizeSimpleLoopInvariant(proc); + mIns[1].mType = ASMIT_LDA; mIns[1].mLive |= LIVE_CPU_REG_A; + mIns[0].mType = ASMIT_CMP; mIns[0].mLive |= LIVE_CPU_REG_Z; + prevBlock->mIns.Push(mIns[1]); + mIns.Remove(1); + return true; + } + int ai = 0; while (ai < mIns.Size() && !mIns[ai].ChangesAccu()) ai++; @@ -11255,7 +11510,11 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc) mTrueJump = this; } - if (sz > 3 && sz < 200 && mNumEntries == 2 && mTrueJump == this) + if (sz == 2 && mTrueJump == this) + { + changed = OptimizeSimpleLoopInvariant(proc, nullptr, nullptr); + } + else if (sz > 3 && sz < 200 && mNumEntries == 2 && mTrueJump == this) { bool simple = true; @@ -13415,6 +13674,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } } #endif + else if (FindExternAddressSumY(i, sreg, breg, ireg)) + { +#if 1 + if (mIns[i + 0].mLive & LIVE_CPU_REG_Y) + { + mIns.Insert(i + 1, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + mIns[i + 1].mLive |= LIVE_CPU_REG_Y; + } + mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg)); + mIns[i + 0].mLive |= LIVE_CPU_REG_Y | LIVE_MEM; + + mIns[i + 1].mAddress = breg; + mIns[i + 1].mFlags &= ~NCIF_YZERO; + progress = true; +#endif + + } } #endif @@ -14380,6 +14656,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 1].mType = ASMIT_ASL; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_C; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 1].mType == ASMIT_ROR && mIns[i + 1].mMode == ASMIM_IMPLIED && + mIns[i + 2].mType == ASMIT_AND && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x80 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + mIns[i + 0].mMode = ASMIM_IMMEDIATE; mIns[i + 0].mAddress = 0; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } #if 1 else if ( mIns[i + 0].mType == ASMIT_ASL && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && @@ -14553,6 +14838,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } #endif + else if ( + mIns[i + 0].mType == ASMIT_LDA && !mIns[i + 0].RequiresXReg() && + mIns[i + 1].mType == ASMIT_LDX && + mIns[i + 2].mType == ASMIT_STX && !(mIns[i + 2].mLive & LIVE_CPU_REG_X) && !mIns[i + 0].MayBeChangedOnAddress(mIns[i + 2])) + { + NativeCodeInstruction ins = mIns[i + 0]; + mIns[i + 0] = mIns[i + 1]; + mIns[i + 1] = mIns[i + 2]; + mIns[i + 2] = ins; + mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A | mIns[i + 2].mLive; + mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= mIns[i + 2].mLive; + progress = true; + } + #if 1 if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress <= 1 && @@ -15600,6 +15899,17 @@ void NativeCodeBasicBlock::BuildPlacement(GrowingArray& p mTrueJump->BuildPlacement(placement); mFalseJump->BuildPlacement(placement); } +#if 1 + else if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mFalseJump->mFalseJump && !mTrueJump->mTrueJump->mPlaced && mTrueJump->mTrueJump->mNumEntries > 1) + { + mTrueJump->mPlaced = true; + mTrueJump->mPlace = placement.Size(); + placement.Push(mTrueJump); + + mFalseJump->BuildPlacement(placement); + mTrueJump->mTrueJump->BuildPlacement(placement); + } +#endif else { mFalseJump->BuildPlacement(placement); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index f32374e..bd07f60 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -224,6 +224,7 @@ public: bool PatchAddressSumY(int at, int reg, int apos, int breg, int ireg); bool FindGlobalAddress(int at, int reg, int& apos); bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags, int & addr); + bool FindExternAddressSumY(int at, int reg, int& breg, int& ireg); bool FindPageStartAddress(int at, int reg, int& addr); bool MoveStoreXUp(int at); bool MoveStoreHighByteDown(int at); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index f250e9c..89b5cd0 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -77,6 +77,13 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { if (!(mdec->mBase->mFlags & DTF_DEFINED)) mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + + if (mdec->mType != DT_VARIABLE) + { + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); + break; + } + mdec->mType = DT_ELEMENT; mdec->mOffset = offset; @@ -319,6 +326,9 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) break; } + dec->mMinValue = minValue; + dec->mMaxValue = maxValue; + if (minValue < 0) { dec->mFlags |= DTF_SIGNED; diff --git a/samples/games/hscrollshmup.c b/samples/games/hscrollshmup.c index 9a6da4f..10316d8 100644 --- a/samples/games/hscrollshmup.c +++ b/samples/games/hscrollshmup.c @@ -2,13 +2,14 @@ #include #include #include +#include #include #include byte * const Screen = (byte *)0xc800; -byte * const Font = (byte *)0xd000; +byte * const Font = (byte *)0xe000; byte * const Color = (byte *)0xd800; -byte * const Sprites = (byte *)0xd800; +byte * const Sprites = (byte *)0xd000; // Character set char charset[2048] = { @@ -19,24 +20,35 @@ char tileset[] = { #embed "../../../assets/uridium1 - Tiles.bin" }; -char tilemap[64 * 5] = { - #embed "../../../assets/uridium1 - Map (64x5).bin" +char tilemap[128 * 5] = { + #embed "../../../assets/uridium1 - Map (128x5).bin" }; char spriteset[2048] = { #embed 2048 0 "../../../assets/uridium1 - Sprites.bin" }; -char xtileset[16][20]; +char xtileset[16][64]; +char xtilemap[144 * 5]; char stars[24]; +#pragma align(xtileset, 64); + void tiles_unpack(void) { - for(char t=0; t<20; t++) + for(char t=0; t<64; t++) { for(char i=0; i<16; i++) xtileset[i][t] = tileset[16 * t + i]; } + + for(char y=0; y<5; y++) + { + for(char x=0; x<144; x++) + { + xtilemap[y * 144 + x] = tilemap[y * 128 + (x & 127)]; + } + } } void tiles_draw0(char * dp, char * tm) @@ -156,22 +168,42 @@ void tiles_draw1(char * dp, char * tm) } } + +struct Shot +{ + char x, y, dx, n; +} shots[5][4]; + +inline void shot_draw(char * dp, char i, char xp, char yp) +{ + char c = dp[xp]; + char * fsp = Font + 8 * c; + char * fdp = Font + 8 * i; + + fdp[0] = fsp[0]; fdp[1] = fsp[1]; fdp[2] = fsp[2]; fdp[3] = fsp[3]; + fdp[4] = fsp[4]; fdp[5] = fsp[5]; fdp[6] = fsp[6]; fdp[7] = fsp[7]; + + fdp[yp] = 0x00; + + dp[xp] = i; +} + void tiles_draw(unsigned x) { char xs = 7 - (x & 7); - vic.ctrl2 = VIC_CTRL2_MCM + xs; - x >>= 3; char xl = x >> 2, xr = x & 3; char yl = 0; + char ci = 192; + char cs = xs | 248; for(int iy=0; iy<5; iy++) { char * dp = Screen + 80 + 160 * iy; char * cp = Color + 80 + 160 * iy; - char * tp = tilemap + xl + 64 * iy; + char * tp = xtilemap + xl + 144 * iy; switch (xr) { @@ -191,15 +223,13 @@ void tiles_draw(unsigned x) __assume(false); } - xs |= 248; - char k = stars[yl + 0] + 0; if (dp[k]) cp[k] = 8; else { cp[k] = 0; - dp[k] = xs; + dp[k] = cs; } k = stars[yl + 1]; @@ -208,7 +238,7 @@ void tiles_draw(unsigned x) else { cp[k] = 0; - dp[k] = xs; + dp[k] = cs; } k = stars[yl + 2]; @@ -217,7 +247,7 @@ void tiles_draw(unsigned x) else { cp[k] = 0; - dp[k] = xs; + dp[k] = cs; } k = stars[yl + 3]; @@ -226,15 +256,32 @@ void tiles_draw(unsigned x) else { cp[k] = 0; - dp[k] = xs; + dp[k] = cs; + } + + + Shot * s = shots[iy]; + for(char si=0; si<4; si++) + { + if (s->n) + { + s->x += s->dx; + s->n--; + shot_draw(dp, ci++, s->x, s->y); + } + s++; } yl += 4; } + + vic.ctrl2 = VIC_CTRL2_MCM + xs; } int main(void) { + cia_init(); + mmap_trampoline(); // Install character set @@ -254,8 +301,8 @@ int main(void) } } - memcpy(Sprites, spriteset, 2048); - mmap_set(MMAP_NO_BASIC); + memcpy(Sprites, spriteset, 4096); + mmap_set(MMAP_NO_ROM); tiles_unpack(); @@ -265,10 +312,10 @@ int main(void) spr_init(Screen); // Change colors - vic.color_border = VCOL_BLUE; + vic.color_border = VCOL_BLACK; vic.color_back = VCOL_WHITE; vic.color_back1 = VCOL_LT_GREY; - vic.color_back2 = VCOL_DARK_GREY; + vic.color_back2 = VCOL_MED_GREY; vic.spr_mcolor0 = VCOL_DARK_GREY; vic.spr_mcolor1 = VCOL_WHITE; @@ -279,12 +326,24 @@ int main(void) for(int i=0; i<24; i++) stars[i] = rand() % 40 + 40 * (i & 3); - spr_set(0, true, 160, 100, 96, 6, true, false, false); + for(int i=0; i<5; i++) + { + for(int j=0; j<8; j++) + { + shots[i][j].x = rand() % 160; + shots[i][j].y = rand() & 7; + } + } + + spr_set(0, true, 160, 100, 64, VCOL_BLUE, true, false, false); + spr_set(1, true, 160, 100, 64 + 16, VCOL_MED_GREY, true, false, false); + vic.spr_priority = 2; int spx = 40; int vpx = 16; int ax = 0; char spy = 100; + char fdelay = 0; for(;;) { @@ -294,39 +353,96 @@ int main(void) ax = joyx[0]; spy += 2 * joyy[0]; + if (spy < 6) + spy = 6; + else if (spy > 6 + 159) + spy = 6 + 159; if (ax > 0) { - if (vpx < 16) + if (vpx < 32) vpx++; - if (vpx == 16) - { - spr_image(0, 96); + else ax = 0; + + if (vpx >= 32) + { + spr_image(0, 64); + spr_image(1, 64 + 16); } else - spr_image(0, 108 + (vpx >> 2)); + { + spr_image(0, 76 + (vpx >> 3)); + spr_image(1, 76 + (vpx >> 3) + 16); + } } else if (ax < 0) { - if (vpx > -15) + if (vpx > - 32) vpx--; - if (vpx == -15) - { - spr_image(0, 104); + else ax = 0; + + if (vpx <= -32) + { + spr_image(0, 72); + spr_image(1, 72 + 16); } else - spr_image(0, 100 - (vpx >> 2)); + { + spr_image(0, 68 - (vpx >> 3)); + spr_image(1, 68 - (vpx >> 3) + 16); + } } - spr_move(0, 160 - 4 * vpx, 50 + spy); + if (fdelay) + fdelay--; + else if (joyb[0] && vpx != 0) + { + char py = spy - 6; + char gy = py >> 5; + char ey = (py >> 3) & 3; + char ry = py & 7; - vic_waitFrame(); + Shot * s = shots[gy]; + + char i = 0; + while (i < 4 && s[i].n != 0) + i++; + + if (i < 4) + { + s[i].y = ry; + if (vpx < 0) + { + s[i].dx = -1; + char x = (148 - 4 * vpx) >> 3; + s[i].n = x - 1; + s[i].x = 40 * ey + x; + } + else if (vpx > 0) + { + s[i].dx = 1; + char x = (156 - 4 * vpx) >> 3; + s[i].x = 40 * ey + x; + s[i].n = 39 - x; + } + fdelay = 4; + } + } + + spr_move(0, 172 - 4 * vpx, 50 + spy); + spr_move(1, 180 - 4 * vpx, 58 + spy); + + vic.color_border++; + vic_waitLine(82); vic.color_border++; tiles_draw(spx); vic.color_border--; + vic.color_border--; spx += vpx >> 1; + + spx &= 4095; } return 0; diff --git a/samples/memmap/easyflash.crt b/samples/memmap/easyflash.crt index 637aa77cb902d5a5a113a260cdc36d47ffff20eb..fe8ad639005a51a13c2741021bafa0ff2a26314d 100644 GIT binary patch delta 275 zcmZ3`#J-@3eS(A_BLf7uCKgw^J8qt|gprVquF6`1@DE_0q_yuiCsx>xYR zN{L>v3qF@QPcmItwK5tczyT3hX^r4)p2T!qmW_dd;Q@of=8r7#(wkTpF>g+==VWAL z*qr6SufWE@z_!GltC8Q;c9477Ur~uN)v!te8?