More cartridge hacking

This commit is contained in:
drmortalwombat 2021-10-19 22:29:23 +02:00
parent 6444428489
commit 9833656fcf
12 changed files with 287 additions and 49 deletions

View File

@ -1,6 +1,19 @@
// crt.c
#include <crt.h>
#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

View File

@ -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

View File

@ -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)

View File

@ -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;
};

View File

@ -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;
@ -265,10 +274,18 @@ void Linker::Link(void)
else if (obj->mType == LOT_SECTION_END)
obj->mAddress = obj->mSection->mEnd;
else if (obj->mFlags & LOBJF_REFERENCED)
{
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);
}
}
}
for (int i = 0; i < mReferences.Size(); i++)
{
@ -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);
fwrite(mCartridge[i] + 0x0000, 1, 0x2000, file);
chipHeader.mLoadAddress = 0x00a0;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(mMemory + 0x2800, 1, 0x2000, 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:
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;
}
}

View File

@ -41,7 +41,9 @@ class LinkerRegion
public:
const Ident* mIdent;
uint32 mFlags;
int mStart, mEnd, mUsed, mNonzero;
int mCartridge;
GrowingArray<LinkerSection*> 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<LinkerObject*> mObjects;
uint8 mMemory[0x10000];
uint8 mCartridge[64][0x4000];
bool mCartridgeBankUsed[64];
int mProgramStart, mProgramEnd;
void ReferenceObject(LinkerObject* obj);

15
oscar64/MachineTypes.cpp Normal file
View File

@ -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;

View File

@ -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;

View File

@ -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);
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();

View File

@ -45,6 +45,8 @@ protected:
Expression* ParseAssemblerAddOperand(void);
Expression* ParseAssemblerOperand(void);
void AddAssemblerRegister(const Ident* ident, int value);
Expression* ParseStatement(void);
Expression* ParseSwitchStatement(void);

View File

@ -154,6 +154,7 @@
<ClCompile Include="InterCode.cpp" />
<ClCompile Include="InterCodeGenerator.cpp" />
<ClCompile Include="Linker.cpp" />
<ClCompile Include="MachineTypes.cpp" />
<ClCompile Include="NativeCodeGenerator.cpp" />
<ClCompile Include="NumberSet.cpp" />
<ClCompile Include="oscar64.cpp" />

View File

@ -72,6 +72,9 @@
<ClCompile Include="GlobalAnalyzer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MachineTypes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Array.h">