diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index cf765e1..6b5deb4 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -1,4 +1,5 @@ #include "Errors.h" +#include "Ident.h" #include #include @@ -8,6 +9,14 @@ Errors::Errors(void) } +void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info) +{ + if (info) + this->Error(loc, eid, msg, info->mString); + else + this->Error(loc, eid, msg); +} + void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info) { const char* level = "info"; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 94c921d..8d0dcbc 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -9,6 +9,8 @@ public: Location() : mFileName(nullptr), mLine(0), mColumn(0) {} }; +class Ident; + enum ErrorID { EINFO_GENERIC = 1000, @@ -67,5 +69,6 @@ public: int mErrorCount; + void Error(const Location& loc, ErrorID eid, const char* msg, const Ident * info); void Error(const Location& loc, ErrorID eid, const char* msg, const char* info = nullptr); }; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index ff1ea7a..1bba52c 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -331,7 +331,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) { procDec->mFlags &= ~DTF_FUNC_INTRSAVE; if (procDec->mFlags & DTF_INTERRUPT) - mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent->mString); + mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent); } if (exp->mRight) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index b47a290..0503cbc 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -140,7 +140,13 @@ void NativeRegisterDataSet::Intersect(const NativeRegisterDataSet& set) NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, LinkerObject* linkerObject, uint32 flags, int param) : mType(type), mMode(mode), mAddress(address), mLinkerObject(linkerObject), mFlags(flags), mParam(param) -{} +{ + if (mode == ASMIM_IMMEDIATE_ADDRESS) + { + assert((mFlags & (NCIF_LOWER | NCIF_UPPER)) != (NCIF_LOWER | NCIF_UPPER)); + assert(HasAsmInstructionMode(mType, ASMIM_IMMEDIATE)); + } +} bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) { @@ -899,6 +905,7 @@ bool NativeCodeInstruction::ApplySimulation(const NativeRegisterDataSet& data) mLinkerObject = data.mRegs[mAddress].mLinkerObject; mFlags = data.mRegs[mAddress].mFlags; mAddress = data.mRegs[mAddress].mValue; + assert((mFlags & (NCIF_LOWER | NCIF_UPPER)) != (NCIF_LOWER | NCIF_UPPER)); return true; } break; @@ -2656,6 +2663,14 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet& } } +void NativeCodeInstruction::CopyMode(const NativeCodeInstruction& ins) +{ + mMode = ins.mMode; + mAddress = ins.mAddress; + mLinkerObject = ins.mLinkerObject; + mFlags = (mFlags & ~(NCIF_LOWER | NCIF_UPPER)) | (ins.mFlags & (NCIF_LOWER | NCIF_UPPER)); +} + void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) { if (mType == ASMIT_BYTE) @@ -2709,6 +2724,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) if (mode == ASMIM_IMMEDIATE_ADDRESS) { + assert((mFlags & (NCIF_LOWER | NCIF_UPPER)) != (NCIF_LOWER | NCIF_UPPER)); assert(HasAsmInstructionMode(mType, ASMIM_IMMEDIATE)); block->PutByte(AsmInsOpcodes[mType][ASMIM_IMMEDIATE]); } @@ -9528,6 +9544,51 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i 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_IMMEDIATE_ADDRESS && (mIns[j + 2].mFlags & NCIF_LOWER) && mIns[j + 2].mLinkerObject && + 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_IMMEDIATE_ADDRESS && (mIns[j + 4].mFlags & NCIF_UPPER) && mIns[j + 4].mLinkerObject == mIns[j + 2].mLinkerObject && + 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) + { + ains = &(mIns[j + 2]); + iins = &(mIns[j + 1]); + apos = j + 0; + + int ireg = iins->mAddress; + if (reg == ireg) + { + if (!direct) + return false; + + flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive; + + int k = j + 7; + while (k < at) + { + if (mIns[k].ChangesYReg()) + flags &= ~LIVE_CPU_REG_Y; + if (mIns[k].ChangesXReg()) + flags &= ~LIVE_CPU_REG_X; + k++; + } + + return flags != 0; + } + else + { + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && 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 && @@ -14617,9 +14678,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 1].mAddress && mIns[i + 3].mType == ASMIT_CMP && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress && !(mIns[i + 3].mLive & LIVE_MEM)) { - mIns[i + 3].mMode = mIns[i + 0].mMode; - mIns[i + 3].mAddress = mIns[i + 0].mAddress; - mIns[i + 3].mLinkerObject = mIns[i + 0].mLinkerObject; + mIns[i + 3].CopyMode(mIns[i + 0]); progress = true; } @@ -15026,7 +15085,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } - if (i + 4 < mIns.Size()) { if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && @@ -15144,7 +15202,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) #endif } - if (i + 3 < mIns.Size()) { if ( @@ -15257,7 +15314,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } } - #if 1 if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y) { @@ -15440,6 +15496,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } while (progress); + if (this->mTrueJump && this->mTrueJump->PeepHoleOptimizer(pass)) changed = true; if (this->mFalseJump && this->mFalseJump->PeepHoleOptimizer(pass)) diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 5fb0655..f32374e 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -71,6 +71,8 @@ public: uint32 mLive; LinkerObject* mLinkerObject; + void CopyMode(const NativeCodeInstruction& ins); + void Assemble(NativeCodeBasicBlock* block); void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps); bool IsUsedResultInstructions(NumberSet& requiredTemps); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index c6b6121..d71ee6d 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -73,7 +73,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.4.90"); + strcpy(strProductVersion, "1.4.91"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 9e0d407..568f6dc 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,90,0 - PRODUCTVERSION 1,4,90,0 + FILEVERSION 1,4,91,0 + PRODUCTVERSION 1,4,91,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.4.90.0" + VALUE "FileVersion", "1.4.91.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.4.90.0" + VALUE "ProductVersion", "1.4.91.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 6e71ede..ff54213 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -3752,15 +3752,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{713950ED-E82C-46AE-AEE1-B7696F19319F}" - "PackageCode" = "8:{9CE6068F-14BD-457A-B770-D8A1BA054207}" + "ProductCode" = "8:{957F0E7A-5C0E-4F4D-B6B3-21C4459CA152}" + "PackageCode" = "8:{C53FBC0A-F69A-4403-AF50-EED9DCFBF363}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.4.90" + "ProductVersion" = "8:1.4.91" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" diff --git a/samples/games/hscrollshmup.c b/samples/games/hscrollshmup.c new file mode 100644 index 0000000..9a6da4f --- /dev/null +++ b/samples/games/hscrollshmup.c @@ -0,0 +1,333 @@ +#include +#include +#include +#include +#include +#include + +byte * const Screen = (byte *)0xc800; +byte * const Font = (byte *)0xd000; +byte * const Color = (byte *)0xd800; +byte * const Sprites = (byte *)0xd800; + +// Character set +char charset[2048] = { + #embed "../../../assets/uridium1 - Chars.bin" +}; + +char tileset[] = { + #embed "../../../assets/uridium1 - Tiles.bin" +}; + +char tilemap[64 * 5] = { + #embed "../../../assets/uridium1 - Map (64x5).bin" +}; + +char spriteset[2048] = { + #embed 2048 0 "../../../assets/uridium1 - Sprites.bin" +}; + +char xtileset[16][20]; +char stars[24]; + +void tiles_unpack(void) +{ + for(char t=0; t<20; t++) + { + for(char i=0; i<16; i++) + xtileset[i][t] = tileset[16 * t + i]; + } +} + +void tiles_draw0(char * dp, char * tm) +{ + for(char x=0; x<10; x++) + { + char ti = tm[x]; + + dp[ 0] = xtileset[ 0][ti]; + dp[ 1] = xtileset[ 1][ti]; + dp[ 2] = xtileset[ 2][ti]; + dp[ 3] = xtileset[ 3][ti]; + dp[ 40] = xtileset[ 4][ti]; + dp[ 41] = xtileset[ 5][ti]; + dp[ 42] = xtileset[ 6][ti]; + dp[ 43] = xtileset[ 7][ti]; + dp[ 80] = xtileset[ 8][ti]; + dp[ 81] = xtileset[ 9][ti]; + dp[ 82] = xtileset[10][ti]; + dp[ 83] = xtileset[11][ti]; + dp[120] = xtileset[12][ti]; + dp[121] = xtileset[13][ti]; + dp[122] = xtileset[14][ti]; + dp[123] = xtileset[15][ti]; + + dp += 4; + } +} + +void tiles_draw3(char * dp, char * tm) +{ + char ti = tm[0]; + + for(char x=1; x<11; x++) + { + dp[ 0] = xtileset[ 3][ti]; + dp[ 40] = xtileset[ 7][ti]; + dp[ 80] = xtileset[11][ti]; + dp[120] = xtileset[15][ti]; + + ti = tm[x]; + + dp[ 1] = xtileset[ 0][ti]; + dp[ 2] = xtileset[ 1][ti]; + dp[ 3] = xtileset[ 2][ti]; + dp[ 41] = xtileset[ 4][ti]; + dp[ 42] = xtileset[ 5][ti]; + dp[ 43] = xtileset[ 6][ti]; + dp[ 81] = xtileset[ 8][ti]; + dp[ 82] = xtileset[ 9][ti]; + dp[ 83] = xtileset[10][ti]; + dp[121] = xtileset[12][ti]; + dp[122] = xtileset[13][ti]; + dp[123] = xtileset[14][ti]; + + dp += 4; + } +} + +void tiles_draw2(char * dp, char * tm) +{ + char ti = tm[0]; + + for(char x=1; x<11; x++) + { + dp[ 0] = xtileset[ 2][ti]; + dp[ 1] = xtileset[ 3][ti]; + dp[ 40] = xtileset[ 6][ti]; + dp[ 41] = xtileset[ 7][ti]; + dp[ 80] = xtileset[10][ti]; + dp[ 81] = xtileset[11][ti]; + dp[120] = xtileset[14][ti]; + dp[121] = xtileset[15][ti]; + + ti = tm[x]; + + dp[ 2] = xtileset[ 0][ti]; + dp[ 3] = xtileset[ 1][ti]; + dp[ 42] = xtileset[ 4][ti]; + dp[ 43] = xtileset[ 5][ti]; + dp[ 82] = xtileset[ 8][ti]; + dp[ 83] = xtileset[ 9][ti]; + dp[122] = xtileset[12][ti]; + dp[123] = xtileset[13][ti]; + + dp += 4; + } +} + +void tiles_draw1(char * dp, char * tm) +{ + char ti = tm[0]; + + for(char x=1; x<11; x++) + { + dp[ 0] = xtileset[ 1][ti]; + dp[ 1] = xtileset[ 2][ti]; + dp[ 2] = xtileset[ 3][ti]; + dp[ 40] = xtileset[ 5][ti]; + dp[ 41] = xtileset[ 6][ti]; + dp[ 42] = xtileset[ 7][ti]; + dp[ 80] = xtileset[ 9][ti]; + dp[ 81] = xtileset[10][ti]; + dp[ 82] = xtileset[11][ti]; + dp[120] = xtileset[13][ti]; + dp[121] = xtileset[14][ti]; + dp[122] = xtileset[15][ti]; + + ti = tm[x]; + + dp[ 3] = xtileset[ 0][ti]; + dp[ 43] = xtileset[ 4][ti]; + dp[ 83] = xtileset[ 8][ti]; + dp[123] = xtileset[12][ti]; + + dp += 4; + } +} + +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; + + 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; + + switch (xr) + { + case 0: + tiles_draw0(dp, tp); + break; + case 1: + tiles_draw1(dp, tp); + break; + case 2: + tiles_draw2(dp, tp); + break; + case 3: + tiles_draw3(dp, tp); + break; + default: + __assume(false); + } + + xs |= 248; + + char k = stars[yl + 0] + 0; + if (dp[k]) + cp[k] = 8; + else + { + cp[k] = 0; + dp[k] = xs; + } + + k = stars[yl + 1]; + if (dp[k]) + cp[k] = 8; + else + { + cp[k] = 0; + dp[k] = xs; + } + + k = stars[yl + 2]; + if (dp[k]) + cp[k] = 8; + else + { + cp[k] = 0; + dp[k] = xs; + } + + k = stars[yl + 3]; + if (dp[k]) + cp[k] = 8; + else + { + cp[k] = 0; + dp[k] = xs; + } + + yl += 4; + } +} + +int main(void) +{ + mmap_trampoline(); + + // Install character set + mmap_set(MMAP_RAM); + memcpy(Font, charset, 2048); + + char * dp = Font + 248 * 8; + + for(int i=0; i<8; i++) + { + for(int j=0; j<8; j++) + { + if (j == 2) + dp[8 * i + j] = ~(1 << i); + else + dp[8 * i + j] = 0xff; + } + } + + memcpy(Sprites, spriteset, 2048); + mmap_set(MMAP_NO_BASIC); + + tiles_unpack(); + + // Switch screen + vic_setmode(VICM_TEXT_MC, Screen, Font); + + spr_init(Screen); + + // Change colors + vic.color_border = VCOL_BLUE; + vic.color_back = VCOL_WHITE; + vic.color_back1 = VCOL_LT_GREY; + vic.color_back2 = VCOL_DARK_GREY; + + vic.spr_mcolor0 = VCOL_DARK_GREY; + vic.spr_mcolor1 = VCOL_WHITE; + + memset(Screen, 0, 1000); + memset(Color, 8, 1000); + + 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); + + int spx = 40; + int vpx = 16; + int ax = 0; + char spy = 100; + + for(;;) + { + joy_poll(0); + + if (ax == 0) + ax = joyx[0]; + + spy += 2 * joyy[0]; + + if (ax > 0) + { + if (vpx < 16) + vpx++; + if (vpx == 16) + { + spr_image(0, 96); + ax = 0; + } + else + spr_image(0, 108 + (vpx >> 2)); + } + else if (ax < 0) + { + if (vpx > -15) + vpx--; + if (vpx == -15) + { + spr_image(0, 104); + ax = 0; + } + else + spr_image(0, 100 - (vpx >> 2)); + } + + spr_move(0, 160 - 4 * vpx, 50 + spy); + + vic_waitFrame(); + vic.color_border++; + tiles_draw(spx); + vic.color_border--; + spx += vpx >> 1; + } + + return 0; +} diff --git a/samples/memmap/easyflash.crt b/samples/memmap/easyflash.crt index bb3b6d1..637aa77 100644 Binary files a/samples/memmap/easyflash.crt and b/samples/memmap/easyflash.crt differ