Prepare support for VIC20 and C128

This commit is contained in:
drmortalwombat 2023-03-02 20:19:47 +01:00
parent e09361295e
commit f34aa2dcbe
10 changed files with 347 additions and 29 deletions

View File

@ -2,6 +2,44 @@
static IOCharMap giocharmap = IOCHM_ASCII; static IOCharMap giocharmap = IOCHM_ASCII;
#if defined(__C128__)
#pragma code(lowcode)
__asm bsout
{
ldx #0
stx 0xff00
jsr 0xffd2
sta 0xff01
}
__asm bsin
{
lda #0
sta 0xff00
jsr 0xffe4
sta 0xff01
}
__asm bsplot
{
lda #0
sta 0xff00
jsr 0xfff0
sta 0xff01
}
__asm bsinit
{
lda #0
sta 0xff00
jsr 0xff81
sta 0xff01
}
#pragma code(code)
#else
#define bsout 0xffd2
#define bsin 0xffe4
#define bsplot 0xfff0
#define bsinit 0xff81
#endif
void iocharmap(IOCharMap chmap) void iocharmap(IOCharMap chmap)
{ {
giocharmap = chmap; giocharmap = chmap;
@ -38,12 +76,12 @@ __asm putpch
beq w3 beq w3
and #$df and #$df
w3: w3:
jmp 0xffd2 jmp bsout
} }
__asm getpch __asm getpch
{ {
jsr 0xffe4 jsr bsin
ldx giocharmap ldx giocharmap
cpx #IOCHM_ASCII cpx #IOCHM_ASCII
@ -117,7 +155,7 @@ void putch(int c)
{ {
__asm { __asm {
lda c lda c
jsr 0xffd2 jsr bsout
} }
} }
@ -125,7 +163,7 @@ void clrscr(void)
{ {
__asm __asm
{ {
jsr $ff5b jsr bsinit
} }
} }
@ -141,7 +179,7 @@ void gotoxy(int cx, int cy)
ldx cy ldx cy
ldy cx ldy cx
clc clc
jsr $fff0 jsr bsplot
} }
} }

View File

@ -145,6 +145,10 @@ w0:
byt 0x00 byt 0x00
byt 0x00 byt 0x00
#if defined(__C128__)
sta 0xff01
#endif
tsx tsx
stx spentry stx spentry
@ -241,6 +245,10 @@ spexit:
sta $13 sta $13
lda #$19 lda #$19
sta $16 sta $16
#if defined(__C128__)
lda #0
sta 0xff00
#endif
rts rts
} }

View File

@ -2,6 +2,37 @@
#include "conio.h" #include "conio.h"
#include "stdlib.h" #include "stdlib.h"
#if defined(__C128__)
#pragma code(lowcode)
__asm bsout
{
ldx #0
stx 0xff00
jsr 0xffd2
sta 0xff01
}
__asm bsplot
{
lda #0
sta 0xff00
jsr 0xfff0
sta 0xff01
}
__asm bsin
{
lda #0
sta 0xff00
jsr 0xffcf
sta 0xff01
}
#pragma code(code)
#else
#define bsout 0xffd2
#define bsplot 0xfff0
#define bsin 0xffcf
#endif
__asm putpch __asm putpch
{ {
ldx giocharmap ldx giocharmap
@ -32,24 +63,24 @@ __asm putpch
beq w3 beq w3
and #$df and #$df
w3: w3:
jmp 0xffd2 jmp bsout
t1: t1:
sec sec
jsr 0xfff0 jsr bsplot
tya tya
and #3 and #3
eor #3 eor #3
tax tax
lda #$20 lda #$20
l1: l1:
jsr 0xffd2 jsr bsout
dex dex
bpl l1 bpl l1
} }
__asm getpch __asm getpch
{ {
jsr 0xffcf jsr bsin
ldx giocharmap ldx giocharmap
cpx #IOCHM_ASCII cpx #IOCHM_ASCII

2
include/vic20/vic.c Normal file
View File

@ -0,0 +1,2 @@
#include "vic.h"

27
include/vic20/vic.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef VIC20_VIC
#define VIC20_VIC
#include <c64/types.h>
struct VICI
{
volatile byte hpos;
volatile byte vpos;
volatile byte ncols;
volatile byte nrows;
volatile byte beam;
volatile byte mempos;
volatile byte hlpen, vlpen;
volatile byte xpaddle, ypaddle;
volatile byte oscfreq[4];
volatile byte volcol;
volatile byte color;
};
#define vici (*((struct VICI *)0x9000))
#pragma compile("vic.c")
#endif

View File

@ -28,7 +28,7 @@ public:
DeclarationScope* mRuntimeScope; DeclarationScope* mRuntimeScope;
LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack, * mSectionZeroPage; LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack, * mSectionZeroPage, * mSectionLowCode;
Linker* mLinker; Linker* mLinker;
bool AddUnit(Location & location, const char* name, const char * from); bool AddUnit(Location & location, const char* name, const char * from);

View File

@ -22,6 +22,7 @@ Compiler::Compiler(void)
mCompilationUnits->mSectionHeap = mLinker->AddSection(Ident::Unique("heap"), LST_HEAP); mCompilationUnits->mSectionHeap = mLinker->AddSection(Ident::Unique("heap"), LST_HEAP);
mCompilationUnits->mSectionStack = mLinker->AddSection(Ident::Unique("stack"), LST_STACK); mCompilationUnits->mSectionStack = mLinker->AddSection(Ident::Unique("stack"), LST_STACK);
mCompilationUnits->mSectionZeroPage = mLinker->AddSection(Ident::Unique("zeropage"), LST_ZEROPAGE); mCompilationUnits->mSectionZeroPage = mLinker->AddSection(Ident::Unique("zeropage"), LST_ZEROPAGE);
mCompilationUnits->mSectionLowCode = nullptr;
mCompilationUnits->mSectionStack->mSize = 4096; mCompilationUnits->mSectionStack->mSize = 4096;
mCompilationUnits->mSectionHeap->mSize = 1024; mCompilationUnits->mSectionHeap->mSize = 1024;
@ -65,6 +66,24 @@ bool Compiler::ParseSource(void)
#endif #endif
} }
switch (mTargetMachine)
{
case TMACH_VIC20:
case TMACH_VIC20_3K:
case TMACH_VIC20_8K:
mCompilationUnits->mSectionStack->mSize = 512;
mCompilationUnits->mSectionHeap->mSize = 512;
break;
case TMACH_VIC20_16K:
case TMACH_VIC20_24K:
mCompilationUnits->mSectionStack->mSize = 1024;
mCompilationUnits->mSectionHeap->mSize = 1024;
break;
case TMACH_C128:
mCompilationUnits->mSectionLowCode = mLinker->AddSection(Ident::Unique("lowcode"), LST_DATA);
break;
}
mPreprocessor->mCompilerOptions = mCompilerOptions; mPreprocessor->mCompilerOptions = mCompilerOptions;
mLinker->mCompilerOptions = mCompilerOptions; mLinker->mCompilerOptions = mCompilerOptions;
@ -177,6 +196,7 @@ bool Compiler::GenerateCode(void)
const Ident* identMain = Ident::Unique("main"); const Ident* identMain = Ident::Unique("main");
const Ident* identCode = Ident::Unique("code"); const Ident* identCode = Ident::Unique("code");
const Ident* identZeroPage = Ident::Unique("zeropage"); const Ident* identZeroPage = Ident::Unique("zeropage");
const Ident* identLowcode = Ident::Unique("lowcode");
LinkerRegion* regionZeroPage = mLinker->FindRegion(identZeroPage); LinkerRegion* regionZeroPage = mLinker->FindRegion(identZeroPage);
if (!regionZeroPage) if (!regionZeroPage)
@ -185,10 +205,61 @@ bool Compiler::GenerateCode(void)
} }
LinkerRegion* regionStartup = mLinker->FindRegion(identStartup); LinkerRegion* regionStartup = mLinker->FindRegion(identStartup);
LinkerRegion* regionLowcode = nullptr;
if (!regionStartup) if (!regionStartup)
{ {
if (mCompilerOptions & COPT_TARGET_PRG) if (mCompilerOptions & COPT_TARGET_PRG)
{
switch (mTargetMachine)
{
case TMACH_C64:
if (mCompilerOptions & COPT_NATIVE)
regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0880);
else
regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900); regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900);
break;
case TMACH_C128:
if (mCompilerOptions & COPT_NATIVE)
{
regionStartup = mLinker->AddRegion(identStartup, 0x1c01, 0x1c80);
regionLowcode = mLinker->AddRegion(identLowcode, 0x1c80, 0x1d00);
}
else
{
regionStartup = mLinker->AddRegion(identStartup, 0x1c01, 0x1c80);
regionLowcode = mLinker->AddRegion(identLowcode, 0x1c80, 0x1d00);
}
regionLowcode->mSections.Push(mCompilationUnits->mSectionLowCode);
break;
case TMACH_C128B:
if (mCompilerOptions & COPT_NATIVE)
regionStartup = mLinker->AddRegion(identStartup, 0x1c01, 0x1c80);
else
regionStartup = mLinker->AddRegion(identStartup, 0x1c01, 0x1d00);
break;
case TMACH_VIC20:
if (mCompilerOptions & COPT_NATIVE)
regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080);
else
regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1100);
break;
case TMACH_VIC20_3K:
if (mCompilerOptions & COPT_NATIVE)
regionStartup = mLinker->AddRegion(identStartup, 0x0401, 0x0480);
else
regionStartup = mLinker->AddRegion(identStartup, 0x0401, 0x0500);
break;
case TMACH_VIC20_8K:
case TMACH_VIC20_16K:
case TMACH_VIC20_24K:
if (mCompilerOptions & COPT_NATIVE)
regionStartup = mLinker->AddRegion(identStartup, 0x1201, 0x1280);
else
regionStartup = mLinker->AddRegion(identStartup, 0x1201, 0x1300);
break;
}
}
else else
regionStartup = mLinker->AddRegion(identStartup, 0x0800, 0x0900); regionStartup = mLinker->AddRegion(identStartup, 0x0800, 0x0900);
} }
@ -198,7 +269,30 @@ bool Compiler::GenerateCode(void)
{ {
regionBytecode = mLinker->FindRegion(identBytecode); regionBytecode = mLinker->FindRegion(identBytecode);
if (!regionBytecode) if (!regionBytecode)
{
switch (mTargetMachine)
{
case TMACH_C64:
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00); regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
break;
case TMACH_C128:
case TMACH_C128B:
regionBytecode = mLinker->AddRegion(identBytecode, 0x1d00, 0x1e00);
break;
case TMACH_VIC20:
regionBytecode = mLinker->AddRegion(identBytecode, 0x1100, 0x1200);
break;
case TMACH_VIC20_3K:
regionBytecode = mLinker->AddRegion(identBytecode, 0x0500, 0x0600);
break;
case TMACH_VIC20_8K:
case TMACH_VIC20_16K:
case TMACH_VIC20_24K:
regionBytecode = mLinker->AddRegion(identBytecode, 0x1300, 0x1400);
break;
}
}
} }
LinkerRegion* regionMain = mLinker->FindRegion(identMain); LinkerRegion* regionMain = mLinker->FindRegion(identMain);
@ -224,9 +318,65 @@ bool Compiler::GenerateCode(void)
if (!(mCompilerOptions & COPT_TARGET_PRG)) if (!(mCompilerOptions & COPT_TARGET_PRG))
regionMain = mLinker->AddRegion(identMain, 0x0900, 0x4700); regionMain = mLinker->AddRegion(identMain, 0x0900, 0x4700);
else if (regionBytecode) else if (regionBytecode)
{
switch (mTargetMachine)
{
case TMACH_C64:
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000); regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
break;
case TMACH_C128:
regionMain = mLinker->AddRegion(identMain, 0x1e00, 0xfe00);
break;
case TMACH_C128B:
regionMain = mLinker->AddRegion(identMain, 0x1e00, 0x4000);
break;
case TMACH_VIC20:
regionMain = mLinker->AddRegion(identMain, 0x1200, 0x1e00);
break;
case TMACH_VIC20_3K:
regionMain = mLinker->AddRegion(identMain, 0x0600, 0x1e00);
break;
case TMACH_VIC20_8K:
regionMain = mLinker->AddRegion(identMain, 0x1400, 0x4000);
break;
case TMACH_VIC20_16K:
regionMain = mLinker->AddRegion(identMain, 0x1400, 0x6000);
break;
case TMACH_VIC20_24K:
regionMain = mLinker->AddRegion(identMain, 0x1400, 0x8000);
break;
}
}
else else
regionMain = mLinker->AddRegion(identMain, 0x0900, 0xa000); {
switch (mTargetMachine)
{
case TMACH_C64:
regionMain = mLinker->AddRegion(identMain, 0x0880, 0xa000);
break;
case TMACH_C128:
regionMain = mLinker->AddRegion(identMain, 0x1d00, 0xfe00);
break;
case TMACH_C128B:
regionMain = mLinker->AddRegion(identMain, 0x1c80, 0x4000);
break;
case TMACH_VIC20:
regionMain = mLinker->AddRegion(identMain, 0x1080, 0x1e00);
break;
case TMACH_VIC20_3K:
regionMain = mLinker->AddRegion(identMain, 0x0580, 0x1e00);
break;
case TMACH_VIC20_8K:
regionMain = mLinker->AddRegion(identMain, 0x1280, 0x4000);
break;
case TMACH_VIC20_16K:
regionMain = mLinker->AddRegion(identMain, 0x1280, 0x6000);
break;
case TMACH_VIC20_24K:
regionMain = mLinker->AddRegion(identMain, 0x1280, 0x8000);
break;
}
}
} }
regionMain->mSections.Push(mCompilationUnits->mSectionCode); regionMain->mSections.Push(mCompilationUnits->mSectionCode);

View File

@ -28,6 +28,7 @@ public:
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions; GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
TargetMachine mTargetMachine;
uint64 mCompilerOptions; uint64 mCompilerOptions;
struct Define struct Define

View File

@ -37,16 +37,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 | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER; static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER;
struct CompilerSettings enum TargetMachine
{ {
uint64 mCompilerFlags; TMACH_C64,
uint8 mRegWork; TMACH_VIC20,
uint8 mRegFParam; TMACH_VIC20_3K,
uint8 mRegIP; TMACH_VIC20_8K,
uint8 mRegAccu; TMACH_VIC20_16K,
uint8 mRegAddr; TMACH_VIC20_24K,
uint8 mRegStack; TMACH_C128,
uint8 mRegLocals; TMACH_C128B
uint8 mRegTmp;
uint8 mRegTmpSaved;
}; };

View File

@ -122,6 +122,9 @@ int main2(int argc, const char** argv)
char targetFormat[20]; char targetFormat[20];
strcpy_s(targetFormat, "prg"); strcpy_s(targetFormat, "prg");
char targetMachine[20];
strcpy_s(targetMachine, "c64");
compiler->AddDefine(Ident::Unique("__OSCAR64C__"), "1"); compiler->AddDefine(Ident::Unique("__OSCAR64C__"), "1");
compiler->AddDefine(Ident::Unique("__STDC__"), "1"); compiler->AddDefine(Ident::Unique("__STDC__"), "1");
compiler->AddDefine(Ident::Unique("__STDC_VERSION__"), "199901L"); compiler->AddDefine(Ident::Unique("__STDC_VERSION__"), "199901L");
@ -161,6 +164,10 @@ int main2(int argc, const char** argv)
{ {
strcpy_s(targetFormat, arg + 4); strcpy_s(targetFormat, arg + 4);
} }
else if (arg[1] == 't' && arg[2] == 'm' && arg[3] == '=')
{
strcpy_s(targetMachine, arg + 4);
}
else if (arg[1] == 'n') else if (arg[1] == 'n')
{ {
compiler->mCompilerOptions |= COPT_NATIVE; compiler->mCompilerOptions |= COPT_NATIVE;
@ -225,11 +232,65 @@ int main2(int argc, const char** argv)
} }
} }
char basicStart[10];
strcpy_s(basicStart, "0x0801");
if (!strcmp(targetMachine, "c64"))
{
compiler->mTargetMachine = TMACH_C64;
compiler->AddDefine(Ident::Unique("__C64__"), "1");
}
else if (!strcmp(targetMachine, "c128"))
{
strcpy_s(basicStart, "0x1c01");
compiler->mTargetMachine = TMACH_C128;
compiler->AddDefine(Ident::Unique("__C128__"), "1");
}
else if (!strcmp(targetMachine, "c128b"))
{
strcpy_s(basicStart, "0x1c01");
compiler->mTargetMachine = TMACH_C128B;
compiler->AddDefine(Ident::Unique("__C128B__"), "1");
}
else if (!strcmp(targetMachine, "vic20"))
{
strcpy_s(basicStart, "0x1001");
compiler->mTargetMachine = TMACH_VIC20;
compiler->AddDefine(Ident::Unique("__VIC20__"), "1");
}
else if (!strcmp(targetMachine, "vic20+3"))
{
strcpy_s(basicStart, "0x0401");
compiler->mTargetMachine = TMACH_VIC20_3K;
compiler->AddDefine(Ident::Unique("__VIC20__"), "1");
}
else if (!strcmp(targetMachine, "vic20+8"))
{
strcpy_s(basicStart, "0x1201");
compiler->mTargetMachine = TMACH_VIC20_8K;
compiler->AddDefine(Ident::Unique("__VIC20__"), "1");
}
else if (!strcmp(targetMachine, "vic20+16"))
{
strcpy_s(basicStart, "0x1201");
compiler->mTargetMachine = TMACH_VIC20_16K;
compiler->AddDefine(Ident::Unique("__VIC20__"), "1");
}
else if (!strcmp(targetMachine, "vic20+24"))
{
strcpy_s(basicStart, "0x1201");
compiler->mTargetMachine = TMACH_VIC20_24K;
compiler->AddDefine(Ident::Unique("__VIC20__"), "1");
}
else
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid target machine option", targetMachine);
if (!strcmp(targetFormat, "prg")) if (!strcmp(targetFormat, "prg"))
{ {
compiler->mCompilerOptions |= COPT_TARGET_PRG; compiler->mCompilerOptions |= COPT_TARGET_PRG;
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_PRG"), "1"); compiler->AddDefine(Ident::Unique("OSCAR_TARGET_PRG"), "1");
compiler->AddDefine(Ident::Unique("OSCAR_BASIC_START"), "0x0801"); compiler->AddDefine(Ident::Unique("OSCAR_BASIC_START"), basicStart);
} }
else if (!strcmp(targetFormat, "crt")) else if (!strcmp(targetFormat, "crt"))
{ {
@ -245,7 +306,7 @@ int main2(int argc, const char** argv)
{ {
compiler->mCompilerOptions |= COPT_TARGET_LZO; compiler->mCompilerOptions |= COPT_TARGET_LZO;
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_LZO"), "1"); compiler->AddDefine(Ident::Unique("OSCAR_TARGET_LZO"), "1");
compiler->AddDefine(Ident::Unique("OSCAR_BASIC_START"), "0x0801"); compiler->AddDefine(Ident::Unique("OSCAR_BASIC_START"), basicStart);
} }
else else
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid target format option", targetFormat); compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid target format option", targetFormat);
@ -302,7 +363,7 @@ int main2(int argc, const char** argv)
} }
else else
{ {
printf("oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=target] [-e] [-n] {-dSYMBOL[=value]} [-v] [-d64=diskname] {-f[z]=file.xxx} {source.c}\n"); printf("oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=target] [-tm=machine] [-e] [-n] {-dSYMBOL[=value]} [-v] [-d64=diskname] {-f[z]=file.xxx} {source.c}\n");
return 0; return 0;
} }