Add more generic cartridge support

This commit is contained in:
drmortalwombat 2023-04-14 18:40:27 +02:00
parent 6308f22f25
commit bb00b5af12
13 changed files with 400 additions and 114 deletions

View File

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

View File

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

View File

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

View File

@ -30,6 +30,7 @@ public:
TargetMachine mTargetMachine;
uint64 mCompilerOptions;
uint16 mCartridgeID;
struct Define
{

View File

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

View File

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

View File

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

View 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);

View File

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

View File

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

View File

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

View File

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

View File

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