From 9833656fcffca018e0ca32a32df46311330f5116 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 19 Oct 2021 22:29:23 +0200 Subject: [PATCH] More cartridge hacking --- include/crt.c | 21 ++++- include/crt.h | 12 --- include/string.c | 33 ++++++++ oscar64/CompilerTypes.h | 14 +++- oscar64/Linker.cpp | 69 ++++++++++++---- oscar64/Linker.h | 7 ++ oscar64/MachineTypes.cpp | 15 ++++ oscar64/MachineTypes.h | 19 +++-- oscar64/Parser.cpp | 140 ++++++++++++++++++++++++++++++-- oscar64/Parser.h | 2 + oscar64/oscar64.vcxproj | 1 + oscar64/oscar64.vcxproj.filters | 3 + 12 files changed, 287 insertions(+), 49 deletions(-) create mode 100644 oscar64/MachineTypes.cpp diff --git a/include/crt.c b/include/crt.c index 903104c..a414bf2 100644 --- a/include/crt.c +++ b/include/crt.c @@ -1,6 +1,19 @@ // crt.c #include +#define tmpy __tmpy +#define tmp __tmp + +#define ip __ip +#define accu __accu +#define addr __addr +#define sp __sp +#define fp __fp + +#define sregs __sregs +#define regs __regs + + void StackStart, StackEnd, BSSStart, BSSEnd; #pragma section(stack, 0x0000, StackStart, StackEnd) @@ -51,12 +64,12 @@ l0: lda (ip), y inc sp + 1 dex bne l0 - lda $01 - and #$fc - ora #$02 - sta $01 jmp w0 w0: + lda #$3f + sta $00 + lda #$36 + sta $01 #else byt 0x0b byt 0x08 diff --git a/include/crt.h b/include/crt.h index 5b0d34a..09691cc 100644 --- a/include/crt.h +++ b/include/crt.h @@ -1,18 +1,6 @@ #ifndef CRT_H #define CRT_H -#define tmpy 0x02 -#define tmp 0x03 - -#define ip 0x19 -#define accu 0x1b -#define addr 0x1f -#define sp 0x23 -#define fp 0x25 - -#define sregs 0x43 -#define regs 0x53 - extern char spentry; enum ByteCode diff --git a/include/string.c b/include/string.c index de74d56..d0a60b4 100644 --- a/include/string.c +++ b/include/string.c @@ -156,10 +156,43 @@ void * memclr(void * dst, int size) void * memcpy(void * dst, const void * src, int size) { + __asm + { + ldx size + 1 + beq _w1 + ldy #0 + _loop1: + lda (src), y + sta (dst), y + iny + bne _loop1 + inc src + 1 + inc dst + 1 + dex + bne _loop1 + _w1: + ldy size + beq _w2 + dey + beq _w3 + _loop2: + lda (src), y + sta (dst), y + dey + bne _loop2 + _w3: + lda (src), y + sta (dst), y + _w2: + } + return dst; +#if 0 + char * d = dst, * s = src; while (size--) *d++ = *s++; return dst; +#endif } void * memmove(void * dst, const void * src, int size) diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index b05ae2a..f9210e3 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -25,4 +25,16 @@ static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_IN static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL; - +struct CompilerSettings +{ + uint64 mCompilerFlags; + uint8 mRegWork; + uint8 mRegFParam; + uint8 mRegIP; + uint8 mRegAccu; + uint8 mRegAddr; + uint8 mRegStack; + uint8 mRegLocals; + uint8 mRegTmp; + uint8 mRegTmpSaved; +}; diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index fda91d4..ffb70be 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -45,7 +45,12 @@ uint8* LinkerObject::AddSpace(int size) Linker::Linker(Errors* errors) : mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr) { - + for (int i = 0; i < 64; i++) + { + mCartridgeBankUsed[i] = 0; + memset(mCartridge[i], 0, 0x4000); + } + memset(mMemory, 0, 0x10000); } Linker::~Linker(void) @@ -62,6 +67,8 @@ LinkerRegion* Linker::AddRegion(const Ident* region, int start, int end) lrgn->mEnd = end; lrgn->mUsed = 0; lrgn->mNonzero = 0; + lrgn->mCartridge = -1; + lrgn->mFlags = 0; mRegions.Push(lrgn); return lrgn; } @@ -136,6 +143,7 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L obj->mSize = 0; obj->mIdent = ident; obj->mSection = section; + obj->mRegion = nullptr; obj->mProc = nullptr; obj->mFlags = 0; section->mObjects.Push(obj); @@ -195,6 +203,7 @@ void Linker::Link(void) lobj->mFlags |= LOBJF_PLACED; lobj->mAddress = lrgn->mStart + lrgn->mUsed; lrgn->mUsed += lobj->mSize; + lobj->mRegion = lrgn; if (lsec->mType == LST_DATA) lrgn->mNonzero = lrgn->mUsed; @@ -266,7 +275,15 @@ void Linker::Link(void) obj->mAddress = obj->mSection->mEnd; else if (obj->mFlags & LOBJF_REFERENCED) { - memcpy(mMemory + obj->mAddress, obj->mData, obj->mSize); + if (obj->mRegion->mCartridge >= 0) + { + mCartridgeBankUsed[obj->mRegion->mCartridge] = true; + memcpy(mCartridge[obj->mRegion->mCartridge] + obj->mAddress - obj->mRegion->mStart, obj->mData, obj->mSize); + } + else + { + memcpy(mMemory + obj->mAddress, obj->mData, obj->mSize); + } } } @@ -279,7 +296,12 @@ void Linker::Link(void) LinkerObject* robj = ref->mRefObject; int raddr = robj->mAddress + ref->mRefOffset; - uint8* dp = mMemory + obj->mAddress + ref->mOffset; + uint8* dp; + + if (obj->mRegion->mCartridge < 0) + dp = mMemory + obj->mAddress + ref->mOffset; + else + dp = mCartridge[obj->mRegion->mCartridge] + obj->mAddress - obj->mRegion->mStart + ref->mOffset; if (ref->mFlags & LREF_LOWBYTE) *dp++ = raddr & 0xff; @@ -353,8 +375,8 @@ bool Linker::WriteCrtFile(const char* filename) criHeader.mHeaderLength = 0x40000000; criHeader.mVersion = 0x0001; criHeader.mHardware = 0x2000; - criHeader.mExrom = 1; - criHeader.mGameLine = 1; + criHeader.mExrom = 0; + criHeader.mGameLine = 0; memset(criHeader.mName, 0, 32); strcpy_s(criHeader.mName, "OSCAR"); @@ -375,22 +397,26 @@ bool Linker::WriteCrtFile(const char* filename) char * bootmem = new char[8192]; + memset(bootmem, 0, 0x2000); + chipHeader.mLoadAddress = 0x0080; fwrite(&chipHeader, sizeof(chipHeader), 1, file); - fwrite(bootmem, 1, 0x2000, file); + fwrite(mMemory + 0x0800, 1, 0x2000, file); + + memcpy(bootmem, mMemory + 0x2800, 0x1800); bootmem[0x1ffc] = 0x00; - bootmem[0x1ffd] = 0xe0; + bootmem[0x1ffd] = 0xff; char bootcode[] = { 0xa9, 0x87, 0x8d, 0x02, 0xde, - 0xa9, 0x01, + 0xa9, 0x00, 0x8d, 0x00, 0xde, 0x6c, 0xfc, 0xff }; - int j = 0; + int j = 0x1f00; for (int i = 0; i < sizeof(bootcode); i++) { bootmem[j++] = 0xa9; @@ -407,15 +433,21 @@ bool Linker::WriteCrtFile(const char* filename) fwrite(&chipHeader, sizeof(chipHeader), 1, file); fwrite(bootmem, 1, 0x2000, file); - chipHeader.mBankNumber = 0x100; + for (int i = 1; i < 64; i++) + { + if (mCartridgeBankUsed[i]) + { + chipHeader.mBankNumber = i << 8; - chipHeader.mLoadAddress = 0x0080; - fwrite(&chipHeader, sizeof(chipHeader), 1, file); - fwrite(mMemory + 0x0800, 1, 0x2000, file); + chipHeader.mLoadAddress = 0x0080; + fwrite(&chipHeader, sizeof(chipHeader), 1, file); + fwrite(mCartridge[i] + 0x0000, 1, 0x2000, file); - chipHeader.mLoadAddress = 0x00a0; - fwrite(&chipHeader, sizeof(chipHeader), 1, file); - fwrite(mMemory + 0x2800, 1, 0x2000, file); + chipHeader.mLoadAddress = 0x00a0; + fwrite(&chipHeader, sizeof(chipHeader), 1, file); + fwrite(mCartridge[i] + 0x2000, 1, 0x2000, file); + } + } fclose(file); return true; @@ -514,7 +546,10 @@ bool Linker::WriteAsmFile(const char* filename) mByteCodeDisassembler.Disassemble(file, mMemory, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this); break; case LOT_NATIVE_CODE: - mNativeDisassembler.Disassemble(file, mMemory, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this); + if (obj->mRegion->mCartridge < 0) + mNativeDisassembler.Disassemble(file, mMemory, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this); + else + mNativeDisassembler.Disassemble(file, mCartridge[obj->mRegion->mCartridge] - obj->mRegion->mStart, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this); break; } } diff --git a/oscar64/Linker.h b/oscar64/Linker.h index 79692ee..e967928 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -41,7 +41,9 @@ class LinkerRegion public: const Ident* mIdent; + uint32 mFlags; int mStart, mEnd, mUsed, mNonzero; + int mCartridge; GrowingArray mSections; @@ -89,6 +91,7 @@ public: int mAddress; int mSize; LinkerSection * mSection; + LinkerRegion * mRegion; uint8 * mData; InterCodeProcedure* mProc; uint32 mFlags; @@ -138,6 +141,10 @@ public: GrowingArray mObjects; uint8 mMemory[0x10000]; + uint8 mCartridge[64][0x4000]; + + bool mCartridgeBankUsed[64]; + int mProgramStart, mProgramEnd; void ReferenceObject(LinkerObject* obj); diff --git a/oscar64/MachineTypes.cpp b/oscar64/MachineTypes.cpp new file mode 100644 index 0000000..5dfd0db --- /dev/null +++ b/oscar64/MachineTypes.cpp @@ -0,0 +1,15 @@ +#include "MachineTypes.h" + +uint8 BC_REG_WORK = 0x03; +uint8 BC_REG_WORK_Y = 0x02; +uint8 BC_REG_FPARAMS = 0x0d; + +uint8 BC_REG_IP = 0x19; +uint8 BC_REG_ACCU = 0x1b; +uint8 BC_REG_ADDR = 0x1f; +uint8 BC_REG_STACK = 0x23; +uint8 BC_REG_LOCALS = 0x25; + +uint8 BC_REG_TMP = 0x43; +uint8 BC_REG_TMP_SAVED = 0x53; + diff --git a/oscar64/MachineTypes.h b/oscar64/MachineTypes.h index af68dd2..026baab 100644 --- a/oscar64/MachineTypes.h +++ b/oscar64/MachineTypes.h @@ -81,15 +81,16 @@ inline int sprintf_s(char* buffer, int size, const char* format, ...) #endif -static const uint8 BC_REG_WORK = 0x03; -static const uint8 BC_REG_FPARAMS = 0x0d; +extern uint8 BC_REG_WORK; +extern uint8 BC_REG_WORK_Y; +extern uint8 BC_REG_FPARAMS; -static const uint8 BC_REG_IP = 0x19; -static const uint8 BC_REG_ACCU = 0x1b; -static const uint8 BC_REG_ADDR = 0x1f; -static const uint8 BC_REG_STACK = 0x23; -static const uint8 BC_REG_LOCALS = 0x25; +extern uint8 BC_REG_IP; +extern uint8 BC_REG_ACCU; +extern uint8 BC_REG_ADDR; +extern uint8 BC_REG_STACK; +extern uint8 BC_REG_LOCALS; -static const uint8 BC_REG_TMP = 0x43; -static const uint8 BC_REG_TMP_SAVED = 0x53; +extern uint8 BC_REG_TMP; +extern uint8 BC_REG_TMP_SAVED; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index fa872ab..c2ed6a0 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2288,6 +2288,16 @@ Expression* Parser::ParseAssemblerOperand(void) return ParseAssemblerAddOperand(); } +void Parser::AddAssemblerRegister(const Ident* ident, int value) +{ + Declaration* decaccu = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + decaccu->mIdent = ident; + decaccu->mBase = TheUnsignedIntTypeDeclaration; + decaccu->mSize = 2; + decaccu->mInteger = value; + mScope->Insert(decaccu->mIdent, decaccu); +} + Expression* Parser::ParseAssembler(void) { DeclarationScope* scope = new DeclarationScope(mScope); @@ -2295,6 +2305,18 @@ Expression* Parser::ParseAssembler(void) mScanner->SetAssemblerMode(true); + AddAssemblerRegister(Ident::Unique("__tmpy"), BC_REG_WORK_Y); + AddAssemblerRegister(Ident::Unique("__tmp"), BC_REG_WORK); + AddAssemblerRegister(Ident::Unique("__ip"), BC_REG_IP); + AddAssemblerRegister(Ident::Unique("__accu"), BC_REG_ACCU); + AddAssemblerRegister(Ident::Unique("__addr"), BC_REG_ADDR); + AddAssemblerRegister(Ident::Unique("__fp"), BC_REG_LOCALS); + AddAssemblerRegister(Ident::Unique("__sp"), BC_REG_STACK); + AddAssemblerRegister(Ident::Unique("__sregs"), BC_REG_TMP_SAVED); + AddAssemblerRegister(Ident::Unique("__regs"), BC_REG_TMP); + + AddAssemblerRegister(Ident::Unique("accu"), BC_REG_ACCU); + Declaration* decaccu = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); decaccu->mIdent = Ident::Unique("accu"); decaccu->mBase = TheUnsignedIntTypeDeclaration; @@ -2612,6 +2634,48 @@ void Parser::ParsePragma(void) } ConsumeToken(TK_CLOSE_PARENTHESIS); } + else if (!strcmp(mScanner->mTokenIdent->mString, "register")) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + if (mScanner->mToken == TK_IDENT) + { + const Ident* reg = mScanner->mTokenIdent; + int index = 0; + mScanner->NextToken(); + + ConsumeToken(TK_COMMA); + Expression* exp = ParseRExpression(); + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER && exp->mDecValue->mInteger >= 2 && exp->mDecValue->mInteger < 0x100) + index = exp->mDecValue->mInteger; + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for start expected"); + + if (!strcmp(reg->mString, "__tmpy")) + BC_REG_WORK_Y = index; + else if (!strcmp(reg->mString, "__tmp")) + BC_REG_WORK = index; + else if (!strcmp(reg->mString, "__ip")) + BC_REG_IP = index; + else if (!strcmp(reg->mString, "__accu")) + BC_REG_ACCU = index; + else if (!strcmp(reg->mString, "__addr")) + BC_REG_ADDR = index; + else if (!strcmp(reg->mString, "__sp")) + BC_REG_STACK = index; + else if (!strcmp(reg->mString, "__fp")) + BC_REG_LOCALS = index; + else if (!strcmp(reg->mString, "__sregs")) + BC_REG_TMP_SAVED = index; + else if (!strcmp(reg->mString, "__regs")) + BC_REG_TMP = index; + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Unknown register name"); + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Register name expected"); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else if (!strcmp(mScanner->mTokenIdent->mString, "bytecode")) { mScanner->NextToken(); @@ -2765,7 +2829,7 @@ void Parser::ParsePragma(void) mScanner->NextToken(); Expression* exp; - int start = 0, end = 0, flags = 0; + int start = 0, end = 0, flags = 0, bank = -1; ConsumeToken(TK_COMMA); @@ -2785,11 +2849,25 @@ void Parser::ParsePragma(void) ConsumeToken(TK_COMMA); - exp = ParseRExpression(); - if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) - flags = exp->mDecValue->mInteger; - else - mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for flags expected"); + if (mScanner->mToken != TK_COMMA) + { + exp = ParseRExpression(); + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + flags = exp->mDecValue->mInteger; + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for flags expected"); + } + + ConsumeToken(TK_COMMA); + + if (mScanner->mToken != TK_COMMA) + { + exp = ParseRExpression(); + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + bank = exp->mDecValue->mInteger; + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for bank expected"); + } LinkerRegion* rgn = mCompilationUnits->mLinker->FindRegion(regionIdent); if (!rgn) @@ -2797,6 +2875,9 @@ void Parser::ParsePragma(void) else if (rgn->mStart != start || rgn->mEnd != end) mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Conflicting linker region definition"); + rgn->mFlags = flags; + rgn->mCartridge = bank; + ConsumeToken(TK_COMMA); ConsumeToken(TK_OPEN_BRACE); if (!ConsumeTokenIf(TK_CLOSE_BRACE)) @@ -2861,6 +2942,9 @@ void Parser::ParsePragma(void) } LinkerSection* lsec = mCompilationUnits->mLinker->FindSection(sectionIdent); + if (!lsec) + lsec = mCompilationUnits->mLinker->AddSection(sectionIdent, LST_DATA); + if (dstart) { dstart->mSection = lsec; @@ -2877,6 +2961,50 @@ void Parser::ParsePragma(void) ConsumeToken(TK_CLOSE_PARENTHESIS); } + else if (!strcmp(mScanner->mTokenIdent->mString, "code")) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + + if (mScanner->mToken == TK_IDENT) + { + const Ident* sectionIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + LinkerSection* lsec = mCompilationUnits->mLinker->FindSection(sectionIdent); + if (lsec) + { + mCodeSection = lsec; + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Section not defined"); + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Section name expected"); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + else if (!strcmp(mScanner->mTokenIdent->mString, "data")) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + + if (mScanner->mToken == TK_IDENT) + { + const Ident* sectionIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + LinkerSection* lsec = mCompilationUnits->mLinker->FindSection(sectionIdent); + if (lsec) + { + mDataSection = lsec; + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Section not defined"); + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Section name expected"); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else { mScanner->NextToken(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index d283396..bc3640e 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -45,6 +45,8 @@ protected: Expression* ParseAssemblerAddOperand(void); Expression* ParseAssemblerOperand(void); + void AddAssemblerRegister(const Ident* ident, int value); + Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); diff --git a/oscar64/oscar64.vcxproj b/oscar64/oscar64.vcxproj index 7cfcc21..c211a60 100644 --- a/oscar64/oscar64.vcxproj +++ b/oscar64/oscar64.vcxproj @@ -154,6 +154,7 @@ + diff --git a/oscar64/oscar64.vcxproj.filters b/oscar64/oscar64.vcxproj.filters index 1c0730c..628676b 100644 --- a/oscar64/oscar64.vcxproj.filters +++ b/oscar64/oscar64.vcxproj.filters @@ -72,6 +72,9 @@ Source Files + + Source Files +