Add overlay support

This commit is contained in:
drmortalwombat 2022-12-10 17:15:25 +01:00
parent 0aa9ca0c70
commit 0055911491
11 changed files with 327 additions and 32 deletions

View File

@ -448,6 +448,22 @@ the start of the stack section. The size of the stack and the minimum size of t
The linker will throw an error if the heap or stack cannot be placed without collision. The linker will throw an error if the heap or stack cannot be placed without collision.
#### Overlays
The linker can generate overlay files that are stored as .prg in the .d64 when selected as target.
The mechanism uses the cartridge bank to denote up to 64 overlays. Each bank can be associated with one overlay file, which will then contain the used content of this bank.
#pragma overlay( ovl1, 1 )
The overlay file can then be loaded in memory during program execution:
krnio_setnam(P"OVL1");
krnio_load(1, 8, 1);
### Inline Assembler ### Inline Assembler
Inline assembler can be embedded inside of any functions, regardles of their compilation target of byte code or native. Inline assembler can be embedded inside of any functions, regardles of their compilation target of byte code or native.
@ -608,6 +624,10 @@ An alternative to calling the function in the cartridge ROM itself is to copy it
This sample will use the memory area starting from 0x0400 for the main code section when copying the code, using the stack page 0x100 for the startup itself, thus wasting small amount of RAM space. This sample will use the memory area starting from 0x0400 for the main code section when copying the code, using the stack page 0x100 for the startup itself, thus wasting small amount of RAM space.
#### Dynamic overlays "overlay.c"
When compiling for .d64 format, the linker will place code and data sections from virtual cartridge banks into overlay files. These files can be loaded when needed and called using normal function calls.
#### Terminate stay resident "tsr.c" #### Terminate stay resident "tsr.c"

View File

@ -546,9 +546,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
while (i > 0 && prgPath[i - 1] != '/' && prgPath[i - 1] != '\\') while (i > 0 && prgPath[i - 1] != '/' && prgPath[i - 1] != '\\')
i--; i--;
d64->OpenFile(prgPath + i); mLinker->WritePrgFile(d64, prgPath + i);
mLinker->WritePrgFile(d64);
d64->CloseFile();
} }
if (mCompilerOptions & COPT_VERBOSE) if (mCompilerOptions & COPT_VERBOSE)

View File

@ -82,14 +82,25 @@ uint8* LinkerObject::AddSpace(int size)
return mData; return mData;
} }
LinkerOverlay::LinkerOverlay(void)
{
}
LinkerOverlay::~LinkerOverlay(void)
{
}
Linker::Linker(Errors* errors) Linker::Linker(Errors* errors)
: mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr), mCompilerOptions(COPT_DEFAULT) : mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr), mOverlays(nullptr), mCompilerOptions(COPT_DEFAULT)
{ {
for (int i = 0; i < 64; i++) for (int i = 0; i < 64; i++)
{ {
mCartridgeBankUsed[i] = 0; mCartridgeBankUsed[i] = 0;
mCartridgeBankSize[i] = 0; mCartridgeBankStart[i] = 0x10000;
memset(mCartridge[i], 0, 0x4000); mCartridgeBankEnd[i] = 0x00000;
memset(mCartridge[i], 0, 0x10000);
} }
memset(mMemory, 0, 0x10000); memset(mMemory, 0, 0x10000);
} }
@ -147,6 +158,17 @@ LinkerSection* Linker::FindSection(const Ident* section)
return nullptr; return nullptr;
} }
LinkerOverlay* Linker::AddOverlay(const Location& location, const Ident* ident, int bank)
{
LinkerOverlay* lovl = new LinkerOverlay;
lovl->mLocation = location;
lovl->mIdent = ident;
lovl->mBank = bank;
mOverlays.Push(lovl);
return lovl;
}
bool Linker::IsSectionPlaced(LinkerSection* section) bool Linker::IsSectionPlaced(LinkerSection* section)
{ {
for (int i = 0; i < mRegions.Size(); i++) for (int i = 0; i < mRegions.Size(); i++)
@ -376,7 +398,7 @@ void Linker::Link(void)
{ {
LinkerRegion* lrgn = mRegions[i]; LinkerRegion* lrgn = mRegions[i];
if (lrgn->mNonzero) if (lrgn->mNonzero && lrgn->mCartridgeBanks == 0)
{ {
if (lrgn->mStart < mProgramStart) if (lrgn->mStart < mProgramStart)
mProgramStart = lrgn->mStart; mProgramStart = lrgn->mStart;
@ -461,9 +483,11 @@ void Linker::Link(void)
if (obj->mRegion->mCartridgeBanks & (1ULL << i)) if (obj->mRegion->mCartridgeBanks & (1ULL << i))
{ {
mCartridgeBankUsed[i] = true; mCartridgeBankUsed[i] = true;
memcpy(mCartridge[i] + obj->mAddress - 0x8000, obj->mData, obj->mSize); memcpy(mCartridge[i] + obj->mAddress, obj->mData, obj->mSize);
if (obj->mAddress - 0x8000 + obj->mSize > mCartridgeBankSize[i]) if (obj->mAddress < mCartridgeBankStart[i])
mCartridgeBankSize[i] = obj->mAddress - 0x8000 + obj->mSize; mCartridgeBankStart[i] = obj->mAddress;
if (obj->mAddress + obj->mSize > mCartridgeBankEnd[i])
mCartridgeBankEnd[i] = obj->mAddress + obj->mSize;
} }
} }
} }
@ -493,7 +517,7 @@ void Linker::Link(void)
{ {
if (obj->mRegion->mCartridgeBanks & (1ULL << i)) if (obj->mRegion->mCartridgeBanks & (1ULL << i))
{ {
dp = mCartridge[i] + obj->mAddress - 0x8000 + ref->mOffset; dp = mCartridge[i] + obj->mAddress + ref->mOffset;
if (ref->mFlags & LREF_LOWBYTE) if (ref->mFlags & LREF_LOWBYTE)
{ {
@ -569,12 +593,38 @@ bool Linker::WriteBinFile(const char* filename)
return false; return false;
} }
bool Linker::WritePrgFile(DiskImage* image) bool Linker::WritePrgFile(DiskImage* image, const char* filename)
{
if (image->OpenFile(filename))
{ {
mMemory[mProgramStart - 2] = mProgramStart & 0xff; mMemory[mProgramStart - 2] = mProgramStart & 0xff;
mMemory[mProgramStart - 1] = mProgramStart >> 8; mMemory[mProgramStart - 1] = mProgramStart >> 8;
return image->WriteBytes(mMemory + mProgramStart - 2, mProgramEnd - mProgramStart + 2); image->WriteBytes(mMemory + mProgramStart - 2, mProgramEnd - mProgramStart + 2);
image->CloseFile();
for (int i = 0; i < mOverlays.Size(); i++)
{
if (image->OpenFile(mOverlays[i]->mIdent->mString))
{
int b = mOverlays[i]->mBank;
int s = mCartridgeBankStart[b];
mCartridge[b][s - 2] = s & 0xff;
mCartridge[b][s - 1] = s >> 8;
image->WriteBytes(mCartridge[b] + s - 2, mCartridgeBankEnd[b] - s + 2);
image->CloseFile();
}
else
return false;
}
return true;
}
return false;
} }
bool Linker::WritePrgFile(const char* filename) bool Linker::WritePrgFile(const char* filename)
@ -742,7 +792,8 @@ bool Linker::WriteCrtFile(const char* filename)
fwrite(bootmem + 0x2000, 1, 0x2000, file); fwrite(bootmem + 0x2000, 1, 0x2000, file);
mCartridgeBankUsed[0] = true; mCartridgeBankUsed[0] = true;
mCartridgeBankSize[0] = usedlz + 0x200; mCartridgeBankStart[0] = 0x8000;
mCartridgeBankEnd[0] = 0x8000 + usedlz + 0x200;
for (int i = 1; i < 64; i++) for (int i = 1; i < 64; i++)
{ {
@ -752,11 +803,11 @@ bool Linker::WriteCrtFile(const char* filename)
chipHeader.mLoadAddress = 0x0080; chipHeader.mLoadAddress = 0x0080;
fwrite(&chipHeader, sizeof(chipHeader), 1, file); fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(mCartridge[i] + 0x0000, 1, 0x2000, file); fwrite(mCartridge[i] + 0x8000, 1, 0x2000, file);
chipHeader.mLoadAddress = 0x00a0; chipHeader.mLoadAddress = 0x00a0;
fwrite(&chipHeader, sizeof(chipHeader), 1, file); fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(mCartridge[i] + 0x2000, 1, 0x2000, file); fwrite(mCartridge[i] + 0xa000, 1, 0x2000, file);
} }
} }
@ -813,7 +864,7 @@ bool Linker::WriteMapFile(const char* filename)
for (int i = 0; i < 64; i++) for (int i = 0; i < 64; i++)
{ {
if (mCartridgeBankUsed[i]) if (mCartridgeBankUsed[i])
fprintf(file, "%02d : %04x\n", i, mCartridgeBankSize[i]); fprintf(file, "%02d : %04x .. %04x (%04x)\n", i, mCartridgeBankStart[i], mCartridgeBankEnd[i], mCartridgeBankEnd[i] - mCartridgeBankStart[i]);
} }
} }
@ -873,7 +924,7 @@ bool Linker::WriteAsmFile(const char* filename)
int i = 0; int i = 0;
while (!(obj->mRegion->mCartridgeBanks & (1ULL << i))) while (!(obj->mRegion->mCartridgeBanks & (1ULL << i)))
i++; i++;
mNativeDisassembler.Disassemble(file, mCartridge[i] - 0x8000, i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this); mNativeDisassembler.Disassemble(file, mCartridge[i], i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
} }
else else
mNativeDisassembler.Disassemble(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this); mNativeDisassembler.Disassemble(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
@ -884,7 +935,7 @@ bool Linker::WriteAsmFile(const char* filename)
int i = 0; int i = 0;
while (!(obj->mRegion->mCartridgeBanks & (1ULL << i))) while (!(obj->mRegion->mCartridgeBanks & (1ULL << i)))
i++; i++;
mNativeDisassembler.DumpMemory(file, mCartridge[i] - 0x8000, i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj); mNativeDisassembler.DumpMemory(file, mCartridge[i], i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
} }
else else
mNativeDisassembler.DumpMemory(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj); mNativeDisassembler.DumpMemory(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);

View File

@ -172,6 +172,17 @@ public:
void MarkRelevant(void); void MarkRelevant(void);
}; };
class LinkerOverlay
{
public:
LinkerOverlay(void);
~LinkerOverlay(void);
Location mLocation;
const Ident * mIdent;
int mBank;
};
class Linker class Linker
{ {
public: public:
@ -190,9 +201,11 @@ public:
LinkerObject * AddObject(const Location & location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment = 1); LinkerObject * AddObject(const Location & location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment = 1);
LinkerOverlay* AddOverlay(const Location& location, const Ident* ident, int bank);
// void AddReference(const LinkerReference& ref); // void AddReference(const LinkerReference& ref);
bool WritePrgFile(DiskImage * image); bool WritePrgFile(DiskImage * image, const char* filename);
bool WritePrgFile(const char* filename); bool WritePrgFile(const char* filename);
bool WriteMapFile(const char* filename); bool WriteMapFile(const char* filename);
bool WriteAsmFile(const char* filename); bool WriteAsmFile(const char* filename);
@ -206,13 +219,14 @@ public:
GrowingArray<LinkerRegion*> mRegions; GrowingArray<LinkerRegion*> mRegions;
GrowingArray<LinkerSection*> mSections; GrowingArray<LinkerSection*> mSections;
GrowingArray<LinkerObject*> mObjects; GrowingArray<LinkerObject*> mObjects;
GrowingArray<LinkerOverlay*> mOverlays;
uint8 mMemory[0x10000]; uint8 mMemory[0x10000];
uint8 mCartridge[64][0x4000]; uint8 mCartridge[64][0x10000];
bool mCartridgeBankUsed[64]; bool mCartridgeBankUsed[64];
uint32 mCartridgeBankSize[64]; uint32 mCartridgeBankStart[64], mCartridgeBankEnd[64];
int mProgramStart, mProgramEnd; int mProgramStart, mProgramEnd;

View File

@ -3607,6 +3607,33 @@ void Parser::ParsePragma(void)
ConsumeToken(TK_CLOSE_PARENTHESIS); ConsumeToken(TK_CLOSE_PARENTHESIS);
} }
else if (!strcmp(mScanner->mTokenIdent->mString, "overlay"))
{
mScanner->NextToken();
ConsumeToken(TK_OPEN_PARENTHESIS);
if (mScanner->mToken == TK_IDENT)
{
const Ident* overlayIdent = mScanner->mTokenIdent;
mScanner->NextToken();
int bank = 0;
ConsumeToken(TK_COMMA);
Expression* exp;
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");
LinkerOverlay* lovl = mCompilationUnits->mLinker->AddOverlay(mScanner->mLocation, overlayIdent, bank);
}
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
else if (!strcmp(mScanner->mTokenIdent->mString, "section")) else if (!strcmp(mScanner->mTokenIdent->mString, "section"))
{ {
mScanner->NextToken(); mScanner->NextToken();

View File

@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
#else #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.11.173"); strcpy(strProductVersion, "1.12.174");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,11,173,0 FILEVERSION 1,12,174,0
PRODUCTVERSION 1,11,173,0 PRODUCTVERSION 1,12,174,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.11.173.0" VALUE "FileVersion", "1.12.174.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.11.173.0" VALUE "ProductVersion", "1.12.174.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -838,6 +838,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_E3FF6A8B315C439DA54DE18DB39FB3AD"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_E4138658F1F544CF86255EDC1659936D" "MsmKey" = "8:_E4138658F1F544CF86255EDC1659936D"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -3777,6 +3783,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "IsolateTo" = "8:"
} }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E3FF6A8B315C439DA54DE18DB39FB3AD"
{
"SourcePath" = "8:..\\samples\\memmap\\overlay.c"
"TargetName" = "8:overlay.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}:_E4138658F1F544CF86255EDC1659936D" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E4138658F1F544CF86255EDC1659936D"
{ {
"SourcePath" = "8:..\\samples\\kernalio\\charread.c" "SourcePath" = "8:..\\samples\\kernalio\\charread.c"
@ -4424,15 +4450,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{B37C3691-BB18-4F82-B574-F47BF7A70D6E}" "ProductCode" = "8:{2FD4FD95-A0D1-4DC0-A9F4-DE9085C7F327}"
"PackageCode" = "8:{1B3B4C99-2560-4BE0-8F6A-05067CD5006F}" "PackageCode" = "8:{9C02A8C7-2D5F-4FAB-8185-219EDC622E4E}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.11.173" "ProductVersion" = "8:1.12.174"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"

View File

@ -10,3 +10,4 @@
../../bin/oscar64 easyflashreloc.c -n -tf=crt ../../bin/oscar64 easyflashreloc.c -n -tf=crt
../../bin/oscar64 easyflashshared.c -n -tf=crt ../../bin/oscar64 easyflashshared.c -n -tf=crt
../../bin/oscar64 tsr.c -n -dNOFLOAT -dNOLONG ../../bin/oscar64 tsr.c -n -dNOFLOAT -dNOLONG
../../bin/oscar64 overlay.c -n -d64=overlay.d64

View File

@ -10,3 +10,4 @@ call ..\..\bin\oscar64 easyflashreloc.c -n -tf=crt
call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt
call ..\..\bin\oscar64 easyflashlow.c -n -tf=crt call ..\..\bin\oscar64 easyflashlow.c -n -tf=crt
call ..\..\bin\oscar64 tsr.c -n -dNOFLOAT -dNOLONG call ..\..\bin\oscar64 tsr.c -n -dNOFLOAT -dNOLONG
call ..\..\bin\oscar64 overlay.c -n -d64=overlay.d64

157
samples/memmap/overlay.c Normal file
View File

@ -0,0 +1,157 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/kernalio.h>
// Common memory area for all overlays
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
// Section and region for first overlay bank
#pragma overlay( ovl1, 1 )
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xc000, , 1, { bcode1, bdata1 } )
// Section and region for second overlay bank
#pragma overlay( ovl2, 2 )
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0xc000, , 2, { bcode2, bdata2 } )
#pragma overlay( ovl3, 3 )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0xc000, , 3, { bcode3, bdata3 } )
#pragma overlay( ovl4, 4 )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0xc000, , 4, { bcode4, bdata4 } )
#pragma overlay( ovl5, 5 )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0xc000, , 5, { bcode5, bdata5 } )
#pragma overlay( ovl6, 6 )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0xc000, , 6, { bcode6, bdata6 } )
// Charwin in shared memory section
CharWin cw;
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first overlay", 7);
cwin_cursor_newline(&cw);
}
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2(void)
{
cwin_put_string(&cw, p"This is second overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3(void)
{
cwin_put_string(&cw, p"This is third overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4(void)
{
cwin_put_string(&cw, p"This is fourth overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5(void)
{
cwin_put_string(&cw, p"This is fifth overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6(void)
{
cwin_put_string(&cw, p"This is sixth overlay", 7);
cwin_cursor_newline(&cw);
}
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
// Load an overlay section into memory
void load(const char * fname)
{
krnio_setnam(fname);
krnio_load(1, 8, 1);
}
int main(void)
{
// Kernal memory only
mmap_set(MMAP_NO_BASIC);
// 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);
// Call function in overlay 1
load(P"OVL1");
print1();
// Call function in overlay 2
load(P"OVL2");
print2();
load(P"OVL3");
print3();
load(P"OVL4");
print4();
load(P"OVL5");
print5();
load(P"OVL6");
print6();
mmap_set(MMAP_ROM);
return 0;
}