Add more generic cartridge support
This commit is contained in:
parent
6308f22f25
commit
bb00b5af12
37
README.md
37
README.md
|
@ -75,20 +75,21 @@ The compiler is command line driven, and creates an executable .prg file.
|
|||
* -n : create pure native code for all functions
|
||||
* -d : define a symbol (e.g. NOFLOAT or NOLONG to avoid float/long code in printf)
|
||||
* -O1 or -O : default optimizations
|
||||
* -O0: disable optimizations
|
||||
* -O2: more aggressive speed optimizations including auto inline of small functions
|
||||
* -O3: aggressive optimization for speed
|
||||
* -Os: optimize for size
|
||||
* -Oi: enable auto inline of small functions (part of O2/O3)
|
||||
* -Oa: optimize inline assembler (part of O2/O3)
|
||||
* -Oz: enable auto placement of global variables in zero page (part of O3)
|
||||
* -g: create source level debug info and add source line numbers to asm listing
|
||||
* -tf: target format, may be prg, crt or bin
|
||||
* -O0 : disable optimizations
|
||||
* -O2 : more aggressive speed optimizations including auto inline of small functions
|
||||
* -O3 : aggressive optimization for speed
|
||||
* -Os : optimize for size
|
||||
* -Oi : enable auto inline of small functions (part of O2/O3)
|
||||
* -Oa : optimize inline assembler (part of O2/O3)
|
||||
* -Oz : enable auto placement of global variables in zero page (part of O3)
|
||||
* -g : create source level debug info and add source line numbers to asm listing
|
||||
* -tf : target format, may be prg, crt or bin
|
||||
* -tm : target machine
|
||||
* -d64 : create a d64 disk image
|
||||
* -f : add a binary file to the disk image
|
||||
* -fz : add a compressed binary file to the disk image
|
||||
* -xz : extended zero page usage, more zero page space, but no return to basic
|
||||
* -cid : cartridge type ID, used by vice emulator
|
||||
|
||||
A list of source files can be provided.
|
||||
|
||||
|
@ -114,6 +115,24 @@ A list of source files can be provided.
|
|||
* atari : Atari 8bit systems, (0x2000..0xbc00)
|
||||
* x16 : Commander X16, (0x0800..0x9f00)
|
||||
|
||||
#### C64 Cartridge formats
|
||||
|
||||
Three cartridge formats are supported
|
||||
|
||||
* -tf=crt : creates an easyflash cartridge with common code expanded from bank 0 into memory
|
||||
* -tf=crt8 : creates a generic 8KB cartridge from 0x8000-0xa000 with autostart header
|
||||
* -tf=crt16 : creates a generic 16KB cartridge from 0x8000-0xc000 with autostart header
|
||||
* -cid=nnn : specifies the type ID, used by vice emul
|
||||
|
||||
The easyflash format cartridge expands the first 16KB bank into memory to provide a
|
||||
common area of "code" and "data". This is taken from the standard code and data section in region "main".
|
||||
|
||||
The generic cartridge formats use the region "rom" from the first bank and include an autostart header.
|
||||
The sections "code" and "data" are placed into this "rom" region. The "bss", "stack" and "heap" sections
|
||||
are placed into the "main" region from 0x0800 to 0x8000.
|
||||
|
||||
The layout can be changed by defining own "main" and "rom" regions.
|
||||
|
||||
### Files generated
|
||||
|
||||
The main file generated by the compiler is a .prg, .crt or .bin with the code and constant data. Additional files are created to support debugging and analysis:
|
||||
|
|
|
@ -64,7 +64,7 @@ __asm p4irq
|
|||
__asm startup
|
||||
{
|
||||
st0:
|
||||
#ifdef OSCAR_TARGET_CRT16
|
||||
#ifdef OSCAR_TARGET_CRT_EASYFLASH
|
||||
byt 0x09
|
||||
byt 0x80
|
||||
byt 0xbc
|
||||
|
@ -165,6 +165,25 @@ w0:
|
|||
lda #$36
|
||||
sta $01
|
||||
|
||||
#elif defined(OSCAR_TARGET_CRT8) || defined(OSCAR_TARGET_CRT16)
|
||||
|
||||
// Start at 0x8000 autostart vectors
|
||||
|
||||
byt 0x09
|
||||
byt 0x80
|
||||
byt 0x09
|
||||
byt 0x80
|
||||
byt 0xc3
|
||||
byt 0xc2
|
||||
byt 0xcd
|
||||
byt 0x38
|
||||
byt 0x30
|
||||
|
||||
lda #$e7
|
||||
sta $01
|
||||
lda #$2f
|
||||
sta $00
|
||||
|
||||
#elif defined(OSCAR_TARGET_BIN)
|
||||
|
||||
#elif defined(__ATARI__)
|
||||
|
|
|
@ -33,6 +33,8 @@ Compiler::Compiler(void)
|
|||
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker, mCompilationUnits->mSectionCode);
|
||||
mInterCodeModule = new InterCodeModule(mErrors, mLinker);
|
||||
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
|
||||
|
||||
mCartridgeID = 0x0000;
|
||||
}
|
||||
|
||||
Compiler::~Compiler(void)
|
||||
|
@ -350,6 +352,11 @@ bool Compiler::GenerateCode(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
|
||||
{
|
||||
regionStartup = mLinker->AddRegion(identStartup, 0x8000, 0x8080);
|
||||
regionStartup->mCartridgeBanks = 1;
|
||||
}
|
||||
else
|
||||
regionStartup = mLinker->AddRegion(identStartup, 0x0800, 0x0900);
|
||||
}
|
||||
|
@ -469,7 +476,11 @@ bool Compiler::GenerateCode(void)
|
|||
switch (mTargetMachine)
|
||||
{
|
||||
case TMACH_C64:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x0880, 0xa000);
|
||||
|
||||
if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
|
||||
regionMain = mLinker->AddRegion(identMain, 0x0800, 0x8000);
|
||||
else
|
||||
regionMain = mLinker->AddRegion(identMain, 0x0880, 0xa000);
|
||||
break;
|
||||
case TMACH_X16:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x0880, 0x9f00);
|
||||
|
@ -540,6 +551,20 @@ bool Compiler::GenerateCode(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (!regionRom)
|
||||
{
|
||||
if (mCompilerOptions & COPT_TARGET_CRT8)
|
||||
{
|
||||
regionRom = mLinker->AddRegion(identRom, 0x8080, 0xa000);
|
||||
regionRom->mCartridgeBanks = 1;
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT16)
|
||||
{
|
||||
regionRom = mLinker->AddRegion(identRom, 0x8080, 0xc000);
|
||||
regionRom->mCartridgeBanks = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (regionRom)
|
||||
{
|
||||
regionRom->mSections.Push(mCompilationUnits->mSectionCode);
|
||||
|
@ -873,12 +898,12 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
|||
mLinker->WritePrgFile(prgPath);
|
||||
}
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT16)
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT)
|
||||
{
|
||||
strcat_s(prgPath, "crt");
|
||||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
printf("Writing <%s>\n", prgPath);
|
||||
mLinker->WriteCrtFile(prgPath);
|
||||
mLinker->WriteCrtFile(prgPath, mCartridgeID);
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_BIN)
|
||||
{
|
||||
|
@ -962,7 +987,7 @@ int Compiler::ExecuteCode(bool profile)
|
|||
emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8;
|
||||
ecode = emu->Emulate(2061);
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT16)
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT)
|
||||
{
|
||||
memcpy(emu->mMemory + 0x8000, mLinker->mMemory + 0x0800, 0x4000);
|
||||
ecode = emu->Emulate(0x8009);
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
|
||||
TargetMachine mTargetMachine;
|
||||
uint64 mCompilerOptions;
|
||||
uint16 mCartridgeID;
|
||||
|
||||
struct Define
|
||||
{
|
||||
|
|
|
@ -2,35 +2,38 @@
|
|||
|
||||
#include "MachineTypes.h"
|
||||
|
||||
static const uint64 COPT_OPTIMIZE_BASIC = 0x00000001;
|
||||
static const uint64 COPT_OPTIMIZE_INLINE = 0x00000002;
|
||||
static const uint64 COPT_OPTIMIZE_ASSEMBLER = 0x00000004;
|
||||
static const uint64 COPT_OPTIMIZE_BASIC = 1ULL << 0;
|
||||
static const uint64 COPT_OPTIMIZE_INLINE = 1ULL << 1;
|
||||
static const uint64 COPT_OPTIMIZE_ASSEMBLER = 1ULL << 2;
|
||||
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_INLINE = 0x00000010;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 0x00000020;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 0x00000040;
|
||||
static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 0x00000100;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_INLINE = 1ULL << 4;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 1ULL << 5;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 1ULL << 6;
|
||||
static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7;
|
||||
static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8;
|
||||
|
||||
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 0x00001000;
|
||||
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16;
|
||||
static const uint64 COPT_NATIVE = 1ULL << 17;
|
||||
static const uint64 COPT_EXTENDED_ZERO_PAGE = 1ULL << 20;
|
||||
|
||||
static const uint64 COPT_EXTENDED_ZERO_PAGE = 0x00010000;
|
||||
static const uint64 COPT_TARGET_PRG = 1ULL << 32;
|
||||
static const uint64 COPT_TARGET_CRT8 = 1ULL << 33;
|
||||
static const uint64 COPT_TARGET_CRT16 = 1ULL << 34;
|
||||
static const uint64 COPT_TARGET_CRT_EASYFLASH = 1ULL << 35;
|
||||
|
||||
static const uint64 COPT_TARGET_PRG = 0x100000000ULL;
|
||||
static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL;
|
||||
static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL;
|
||||
static const uint64 COPT_TARGET_COPY = 0x800000000ULL;
|
||||
static const uint64 COPT_TARGET_BIN = 0x1000000000ULL;
|
||||
static const uint64 COPT_TARGET_LZO = 0x2000000000ULL;
|
||||
static const uint64 COPT_TARGET_NES = 0x4000000000ULL;
|
||||
static const uint64 COPT_TARGET_CRT = COPT_TARGET_CRT8 | COPT_TARGET_CRT16 | COPT_TARGET_CRT_EASYFLASH;
|
||||
|
||||
static const uint64 COPT_VERBOSE = 0x10000000000ULL;
|
||||
static const uint64 COPT_VERBOSE2 = 0x20000000000ULL;
|
||||
static const uint64 COPT_VERBOSE3 = 0x40000000000ULL;
|
||||
static const uint64 COPT_TARGET_COPY = 1ULL << 36;
|
||||
static const uint64 COPT_TARGET_BIN = 1ULL << 37;
|
||||
static const uint64 COPT_TARGET_LZO = 1ULL << 38;
|
||||
static const uint64 COPT_TARGET_NES = 1ULL << 39;
|
||||
|
||||
static const uint64 COPT_DEBUGINFO = 0x100000000000ULL;
|
||||
static const uint64 COPT_VERBOSE = 1ULL << 48;
|
||||
static const uint64 COPT_VERBOSE2 = 1ULL << 49;
|
||||
static const uint64 COPT_VERBOSE3 = 1ULL << 50;
|
||||
|
||||
static const uint64 COPT_DEBUGINFO = 1ULL << 51;
|
||||
|
||||
static const uint64 COPT_NATIVE = 0x01000000;
|
||||
|
||||
static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
|
||||
|
||||
|
|
|
@ -451,7 +451,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
}
|
||||
else if (exp->mDecValue->mType == DT_CONST_POINTER)
|
||||
{
|
||||
RegisterProc(Analyze(exp->mDecValue->mValue, procDec, false));
|
||||
RegisterProc(Analyze(exp->mDecValue->mValue, procDec, true));
|
||||
}
|
||||
else if (exp->mDecValue->mType == DT_CONST_ADDRESS)
|
||||
{
|
||||
|
|
|
@ -820,7 +820,17 @@ static int memlzcomp(uint8 * dp, const uint8 * sp, int size)
|
|||
return csize;
|
||||
}
|
||||
|
||||
bool Linker::WriteCrtFile(const char* filename)
|
||||
static uint16 flip16(uint16 w)
|
||||
{
|
||||
return (w >> 8) | (w << 8);
|
||||
}
|
||||
|
||||
static uint32 flip32(uint32 d)
|
||||
{
|
||||
return uint32(flip16(uint16(d >> 16))) | (uint32(flip16(uint16(d))) << 16);
|
||||
}
|
||||
|
||||
bool Linker::WriteCrtFile(const char* filename, uint16 id)
|
||||
{
|
||||
FILE* file;
|
||||
fopen_s(&file, filename, "wb");
|
||||
|
@ -830,7 +840,8 @@ bool Linker::WriteCrtFile(const char* filename)
|
|||
{
|
||||
char mSignature[16];
|
||||
uint32 mHeaderLength;
|
||||
uint16 mVersion, mHardware;
|
||||
uint16 mVersion;
|
||||
uint8 mIDHi, mIDLo;
|
||||
uint8 mExrom, mGameLine;
|
||||
uint8 mPad[6];
|
||||
char mName[32];
|
||||
|
@ -839,9 +850,25 @@ bool Linker::WriteCrtFile(const char* filename)
|
|||
memcpy(criHeader.mSignature, "C64 CARTRIDGE ", 16);
|
||||
criHeader.mHeaderLength = 0x40000000;
|
||||
criHeader.mVersion = 0x0001;
|
||||
criHeader.mHardware = 0x2000;
|
||||
criHeader.mExrom = 0;
|
||||
criHeader.mGameLine = 0;
|
||||
criHeader.mIDHi = uint8(id >> 8);
|
||||
criHeader.mIDLo = uint8(id & 0xff);
|
||||
|
||||
if (mCompilerOptions & COPT_TARGET_CRT8)
|
||||
{
|
||||
criHeader.mExrom = 0;
|
||||
criHeader.mGameLine = 1;
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT16)
|
||||
{
|
||||
criHeader.mExrom = 0;
|
||||
criHeader.mGameLine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
criHeader.mExrom = 0;
|
||||
criHeader.mGameLine = 0;
|
||||
}
|
||||
|
||||
memset(criHeader.mName, 0, 32);
|
||||
strcpy_s(criHeader.mName, "OSCAR");
|
||||
|
||||
|
@ -854,80 +881,132 @@ bool Linker::WriteCrtFile(const char* filename)
|
|||
uint16 mChipType, mBankNumber, mLoadAddress, mImageSize;
|
||||
} chipHeader = { 0 };
|
||||
|
||||
memcpy(chipHeader.mSignature, "CHIP", 4);
|
||||
chipHeader.mPacketLength = 0x10200000;
|
||||
chipHeader.mChipType = 0;
|
||||
chipHeader.mBankNumber = 0;
|
||||
chipHeader.mImageSize = 0x0020;
|
||||
|
||||
uint8 bootmem[0x4000];
|
||||
|
||||
memset(bootmem, 0, 0x4000);
|
||||
|
||||
LinkerRegion * mainRegion = FindRegion(Ident::Unique("main"));
|
||||
LinkerRegion * startupRegion = FindRegion(Ident::Unique("startup"));
|
||||
|
||||
memcpy(bootmem, mMemory + startupRegion->mStart, startupRegion->mNonzero - startupRegion->mStart);
|
||||
int usedlz = memlzcomp(bootmem + 0x0100, mMemory + mainRegion->mStart, mainRegion->mNonzero - mainRegion->mStart);
|
||||
|
||||
Location loc;
|
||||
|
||||
if (usedlz > 0x03e00)
|
||||
if (mCompilerOptions & COPT_TARGET_CRT_EASYFLASH) // EASYFLASH
|
||||
{
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Can not fit main region into first ROM bank");
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
memcpy(chipHeader.mSignature, "CHIP", 4);
|
||||
chipHeader.mPacketLength = 0x10200000;
|
||||
chipHeader.mChipType = 0;
|
||||
chipHeader.mBankNumber = 0;
|
||||
chipHeader.mImageSize = 0x0020;
|
||||
|
||||
bootmem[0x3ffc] = 0x00;
|
||||
bootmem[0x3ffd] = 0xff;
|
||||
uint8 bootmem[0x4000];
|
||||
|
||||
uint8 bootcode[] = {
|
||||
0xa9, 0x87,
|
||||
0x8d, 0x02, 0xde,
|
||||
0xa9, 0x00,
|
||||
0x8d, 0x00, 0xde,
|
||||
0x6c, 0xfc, 0xff
|
||||
};
|
||||
memset(bootmem, 0, 0x4000);
|
||||
|
||||
int j = 0x3f00;
|
||||
for (int i = 0; i < sizeof(bootcode); i++)
|
||||
{
|
||||
bootmem[j++] = 0xa9;
|
||||
bootmem[j++] = bootcode[i];
|
||||
bootmem[j++] = 0x8d;
|
||||
bootmem[j++] = i;
|
||||
bootmem[j++] = 0x04;
|
||||
}
|
||||
bootmem[j++] = 0x4c;
|
||||
bootmem[j++] = 0x00;
|
||||
bootmem[j++] = 0x04;
|
||||
LinkerRegion* mainRegion = FindRegion(Ident::Unique("main"));
|
||||
LinkerRegion* startupRegion = FindRegion(Ident::Unique("startup"));
|
||||
|
||||
chipHeader.mLoadAddress = 0x0080;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(bootmem, 1, 0x2000, file);
|
||||
memcpy(bootmem, mMemory + startupRegion->mStart, startupRegion->mNonzero - startupRegion->mStart);
|
||||
int usedlz = memlzcomp(bootmem + 0x0100, mMemory + mainRegion->mStart, mainRegion->mNonzero - mainRegion->mStart);
|
||||
|
||||
chipHeader.mLoadAddress = 0x00e0;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(bootmem + 0x2000, 1, 0x2000, file);
|
||||
Location loc;
|
||||
|
||||
mCartridgeBankUsed[0] = true;
|
||||
mCartridgeBankStart[0] = 0x8000;
|
||||
mCartridgeBankEnd[0] = 0x8000 + usedlz + 0x200;
|
||||
|
||||
for (int i = 1; i < 64; i++)
|
||||
{
|
||||
if (mCartridgeBankUsed[i])
|
||||
if (usedlz > 0x03e00)
|
||||
{
|
||||
chipHeader.mBankNumber = i << 8;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Can not fit main region into first ROM bank");
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
chipHeader.mLoadAddress = 0x0080;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(mCartridge[i] + 0x8000, 1, 0x2000, file);
|
||||
bootmem[0x3ffc] = 0x00;
|
||||
bootmem[0x3ffd] = 0xff;
|
||||
|
||||
chipHeader.mLoadAddress = 0x00a0;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(mCartridge[i] + 0xa000, 1, 0x2000, file);
|
||||
uint8 bootcode[] = {
|
||||
0xa9, 0x87,
|
||||
0x8d, 0x02, 0xde,
|
||||
0xa9, 0x00,
|
||||
0x8d, 0x00, 0xde,
|
||||
0x6c, 0xfc, 0xff
|
||||
};
|
||||
|
||||
int j = 0x3f00;
|
||||
for (int i = 0; i < sizeof(bootcode); i++)
|
||||
{
|
||||
bootmem[j++] = 0xa9;
|
||||
bootmem[j++] = bootcode[i];
|
||||
bootmem[j++] = 0x8d;
|
||||
bootmem[j++] = i;
|
||||
bootmem[j++] = 0x04;
|
||||
}
|
||||
bootmem[j++] = 0x4c;
|
||||
bootmem[j++] = 0x00;
|
||||
bootmem[j++] = 0x04;
|
||||
|
||||
chipHeader.mLoadAddress = 0x0080;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(bootmem, 1, 0x2000, file);
|
||||
|
||||
chipHeader.mLoadAddress = 0x00e0;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(bootmem + 0x2000, 1, 0x2000, file);
|
||||
|
||||
mCartridgeBankUsed[0] = true;
|
||||
mCartridgeBankStart[0] = 0x8000;
|
||||
mCartridgeBankEnd[0] = 0x8000 + usedlz + 0x200;
|
||||
|
||||
for (int i = 1; i < 64; i++)
|
||||
{
|
||||
if (mCartridgeBankUsed[i])
|
||||
{
|
||||
chipHeader.mBankNumber = i << 8;
|
||||
|
||||
chipHeader.mLoadAddress = 0x0080;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(mCartridge[i] + 0x8000, 1, 0x2000, file);
|
||||
|
||||
chipHeader.mLoadAddress = 0x00a0;
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(mCartridge[i] + 0xa000, 1, 0x2000, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT8)
|
||||
{
|
||||
int numBanks = 64;
|
||||
while (numBanks > 1 && !mCartridgeBankUsed[numBanks - 1])
|
||||
numBanks--;
|
||||
|
||||
memcpy(chipHeader.mSignature, "CHIP", 4);
|
||||
chipHeader.mPacketLength = flip32(0x10 + 0x2000);
|
||||
chipHeader.mChipType = 0;
|
||||
chipHeader.mBankNumber = 0;
|
||||
chipHeader.mImageSize = flip16(0x2000);
|
||||
|
||||
for (int i = 0; i < numBanks; i++)
|
||||
{
|
||||
if (mCartridgeBankUsed[i])
|
||||
{
|
||||
chipHeader.mBankNumber = flip16(uint16(i));
|
||||
|
||||
chipHeader.mLoadAddress = flip16(0x8000);
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(mCartridge[i] + 0x8000, 1, 0x2000, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_CRT16)
|
||||
{
|
||||
int numBanks = 64;
|
||||
while (numBanks > 1 && !mCartridgeBankUsed[numBanks - 1])
|
||||
numBanks--;
|
||||
|
||||
memcpy(chipHeader.mSignature, "CHIP", 4);
|
||||
chipHeader.mPacketLength = flip32(0x10 + 0x4000);
|
||||
chipHeader.mChipType = 0;
|
||||
chipHeader.mBankNumber = 0;
|
||||
chipHeader.mImageSize = flip16(0x4000);
|
||||
|
||||
for (int i = 0; i < numBanks; i++)
|
||||
{
|
||||
if (mCartridgeBankUsed[i])
|
||||
{
|
||||
chipHeader.mBankNumber = flip16(uint16(i));
|
||||
|
||||
chipHeader.mLoadAddress = flip16(0x8000);
|
||||
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
|
||||
fwrite(mCartridge[i] + 0x8000, 1, 0x4000, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
bool WriteMapFile(const char* filename);
|
||||
bool WriteAsmFile(const char* filename);
|
||||
bool WriteLblFile(const char* filename);
|
||||
bool WriteCrtFile(const char* filename);
|
||||
bool WriteCrtFile(const char* filename, uint16 id);
|
||||
bool WriteBinFile(const char* filename);
|
||||
bool WriteNesFile(const char* filename, TargetMachine machine);
|
||||
bool WriteMlbFile(const char* filename, TargetMachine machine);
|
||||
|
|
|
@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
|
|||
|
||||
#else
|
||||
strcpy(strProductName, "oscar64");
|
||||
strcpy(strProductVersion, "1.18.197");
|
||||
strcpy(strProductVersion, "1.19.198");
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint32_t length = sizeof(basePath);
|
||||
|
@ -168,6 +168,12 @@ int main2(int argc, const char** argv)
|
|||
{
|
||||
strcpy_s(targetMachine, arg + 4);
|
||||
}
|
||||
else if (arg[1] == 'c' && arg[2] == 'i' && arg[3] == 'd' && arg[4] == '=')
|
||||
{
|
||||
char cid[10];
|
||||
strcpy_s(cid, arg + 5);
|
||||
compiler->mCartridgeID = atoi(cid);
|
||||
}
|
||||
else if (arg[1] == 'n')
|
||||
{
|
||||
compiler->mCompilerOptions |= COPT_NATIVE;
|
||||
|
@ -378,10 +384,22 @@ int main2(int argc, const char** argv)
|
|||
compiler->AddDefine(Ident::Unique("OSCAR_BASIC_START"), basicStart);
|
||||
}
|
||||
else if (!strcmp(targetFormat, "crt"))
|
||||
{
|
||||
compiler->mCompilerOptions |= COPT_TARGET_CRT_EASYFLASH;
|
||||
compiler->mCartridgeID = 0x0020;
|
||||
|
||||
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_CRT_EASYFLASH"), "1");
|
||||
}
|
||||
else if (!strcmp(targetFormat, "crt16"))
|
||||
{
|
||||
compiler->mCompilerOptions |= COPT_TARGET_CRT16;
|
||||
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_CRT16"), "1");
|
||||
}
|
||||
else if (!strcmp(targetFormat, "crt8"))
|
||||
{
|
||||
compiler->mCompilerOptions |= COPT_TARGET_CRT8;
|
||||
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_CRT8"), "1");
|
||||
}
|
||||
else if (!strcmp(targetFormat, "bin"))
|
||||
{
|
||||
compiler->mCompilerOptions |= COPT_TARGET_BIN;
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,18,197,0
|
||||
PRODUCTVERSION 1,18,197,0
|
||||
FILEVERSION 1,19,198,0
|
||||
PRODUCTVERSION 1,19,198,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,12 +43,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "oscar64"
|
||||
VALUE "FileDescription", "oscar64 compiler"
|
||||
VALUE "FileVersion", "1.18.197.0"
|
||||
VALUE "FileVersion", "1.19.198.0"
|
||||
VALUE "InternalName", "oscar64.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||
VALUE "OriginalFilename", "oscar64.exe"
|
||||
VALUE "ProductName", "oscar64"
|
||||
VALUE "ProductVersion", "1.18.197.0"
|
||||
VALUE "ProductVersion", "1.19.198.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -856,6 +856,12 @@
|
|||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_CACD2FA2FFF3488AB6C5A0E5980B7805"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_CC473A7B399D4B31A9DC8C94F7771EF7"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
|
@ -3987,6 +3993,26 @@
|
|||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CACD2FA2FFF3488AB6C5A0E5980B7805"
|
||||
{
|
||||
"SourcePath" = "8:..\\samples\\memmap\\magicdesk.c"
|
||||
"TargetName" = "8:magicdesk.c"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_A62A71A6A08941C5964B90112D87731F"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CC473A7B399D4B31A9DC8C94F7771EF7"
|
||||
{
|
||||
"SourcePath" = "8:..\\samples\\memmap\\charsethi.c"
|
||||
|
@ -5129,15 +5155,15 @@
|
|||
{
|
||||
"Name" = "8:Microsoft Visual Studio"
|
||||
"ProductName" = "8:oscar64"
|
||||
"ProductCode" = "8:{BD84D458-D051-4806-8F62-7615360BA28B}"
|
||||
"PackageCode" = "8:{E20C48E9-5990-4069-B296-44E92B26D64F}"
|
||||
"ProductCode" = "8:{1E7DBEE1-2479-49F8-9F5B-1DA786C469FD}"
|
||||
"PackageCode" = "8:{F178C72F-3E89-41CE-8310-E30ADA97F214}"
|
||||
"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.18.197"
|
||||
"ProductVersion" = "8:1.19.198"
|
||||
"Manufacturer" = "8:oscar64"
|
||||
"ARPHELPTELEPHONE" = "8:"
|
||||
"ARPHELPLINK" = "8:"
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
#include <c64/memmap.h>
|
||||
#include <c64/charwin.h>
|
||||
#include <c64/cia.h>
|
||||
#include <c64/vic.h>
|
||||
|
||||
// Set rom region end at 0x9f80 to leave some space for copy code
|
||||
#pragma region(rom, 0x8080, 0x9f80, , 0, { code, data } )
|
||||
|
||||
// We do not want to pollute main RAM region with our data
|
||||
#pragma region(main, 0xc000, 0xd000, , , { bss, stack, heap })
|
||||
#pragma stacksize( 256 )
|
||||
|
||||
// Region and code for a cross bank copy routine
|
||||
#pragma section( ccode, 0 )
|
||||
#pragma region( crom, 0x9f80, 0xa000, , 0, { ccode }, 0x0380 )
|
||||
|
||||
CharWin cw;
|
||||
|
||||
// Copy code from any bank to RAM, returns to bank 0, this code is
|
||||
// copied from bank 0 to RAM at 0x0380 at program start
|
||||
|
||||
#pragma code ( ccode )
|
||||
|
||||
__export void ccopy(char bank, char * dst, const char * src, unsigned n)
|
||||
{
|
||||
*((volatile char *)0xde00) = bank;
|
||||
while (n)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
n--;
|
||||
}
|
||||
*((volatile char *)0xde00) = 0;
|
||||
}
|
||||
|
||||
// Region of code to be executed from RAM after copied from 2nd ROM
|
||||
// bank
|
||||
|
||||
#pragma section( bcode1, 0 )
|
||||
#pragma section( bdata1, 0 )
|
||||
#pragma region(bank1, 0x8000, 0xa000, , 1, { bcode1, bdata1 }, 0x2000 )
|
||||
|
||||
#pragma code ( bcode1 )
|
||||
#pragma data ( bdata1 )
|
||||
|
||||
// Print into shared charwin
|
||||
|
||||
void print1(void)
|
||||
{
|
||||
cwin_put_string(&cw, p"This is first bank", 1);
|
||||
cwin_cursor_newline(&cw);
|
||||
}
|
||||
|
||||
// Back to main sections in bank 0
|
||||
|
||||
#pragma code ( code )
|
||||
#pragma data ( data )
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Enable ROM
|
||||
mmap_set(MMAP_ROM);
|
||||
|
||||
// Init CIAs (no kernal rom was executed so far)
|
||||
cia_init();
|
||||
|
||||
// Copy ccopy code to RAM
|
||||
for(char i=0; i<128; i++)
|
||||
((char *)0x0380)[i] = ((char *)0x9f80)[i];
|
||||
|
||||
// Init VIC
|
||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
|
||||
|
||||
// Prepare output window
|
||||
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
|
||||
cwin_clear(&cw);
|
||||
|
||||
// Write first line
|
||||
cwin_put_string(&cw, p"Hello World", 7);
|
||||
cwin_cursor_newline(&cw);
|
||||
|
||||
// Copy bank 1 to RAM
|
||||
ccopy(1, (char *)0x2000, (char *)0x8000, 0x2000);
|
||||
|
||||
// Call function in copy
|
||||
print1();
|
||||
|
||||
// Third line
|
||||
cwin_put_string(&cw, p"Final words", 14);
|
||||
cwin_cursor_newline(&cw);
|
||||
|
||||
while (true) ;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -11,3 +11,4 @@ call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt
|
|||
call ..\..\bin\oscar64 easyflashlow.c -n -tf=crt
|
||||
call ..\..\bin\oscar64 tsr.c -n -dNOFLOAT -dNOLONG
|
||||
call ..\..\bin\oscar64 overlay.c -n -d64=overlay.d64
|
||||
call ..\..\bin\oscar64 magicdesk.c -n -tf=crt8 -cid=19
|
||||
|
|
Loading…
Reference in New Issue