diff --git a/include/c128/vdc.c b/include/c128/vdc.c new file mode 100644 index 00000000..fa4f6add --- /dev/null +++ b/include/c128/vdc.c @@ -0,0 +1,78 @@ +#include "vdc.h" + + +inline void vdc_reg(VDCRegister reg) +{ + vdc.addr = reg; + do {} while (vdc.addr < 128); +} + +inline void vdc_write(byte data) +{ + vdc.data = data; +} + +inline byte vdc_read(void) +{ + return vdc.data; +} + + +void vdc_reg_write(VDCRegister reg, byte data) +{ + vdc_reg(reg); + vdc_write(data); +} + +byte vdc_reg_read(VDCRegister reg) +{ + vdc_reg(reg); + return vdc_read(); +} + + +void vdc_mem_addr(unsigned addr) +{ + vdc_reg_write(VDCR_ADDRH, addr >> 8); + vdc_reg_write(VDCR_ADDRL, addr); + vdc_reg(VDCR_DATA); +} + +inline void vdc_mem_write(char data) +{ + vdc_write(data); +} + +inline char vdc_mem_read(void) +{ + return vdc_read(); +} + + +void vdc_mem_write_at(unsigned addr, char data) +{ + vdc_mem_addr(addr); + vdc_write(data); +} + +char vdc_mem_read_at(unsigned addr) +{ + vdc_mem_addr(addr); + return vdc_read(); +} + + +void vdc_mem_write_buffer(unsigned addr, const char * data, char size) +{ + vdc_mem_addr(addr); + for(char i=0; i + +enum VDCRegister +{ + VDCR_HTOTAL, + VDCR_HDISPLAY, + VDCR_HSYNC, + VDCR_SYNCSIZE, + + VDCR_VTOTAL, + VDCR_VADJUST, + VDCR_VDISPLAY, + VDCR_VSYNC, + + VDCR_LACE, + VDCR_CSIZE, + VDCR_CURSOR_START, + VDCR_CURSOR_END, + + VDCR_DISP_ADDRH, + VDCR_DISP_ADDRL, + VDCR_CURSOR_ADDRH, + VDCR_CURSOR_ADDRL, + + VDCR_LPEN_Y, + VDCR_LPEN_X, + VDCR_ADDRH, + VDCR_ADDRL, + + VDCR_ATTR_ADDRH, + VDCR_ATTR_ADDRL, + VDCR_CWIDTH, + VDCR_CHEIGHT, + + VDCR_VSCROLL, + VDCR_HSCROLL, + VDCR_COLOR, + VDCR_ROWINC, + + VDCR_CHAR_ADDRH, + VDCR_UNDERLINE, + VDCR_DSIZE, + VDCR_DATA, + + VDCR_BLOCK_ADDRH, + VDCR_BLOCK_ADDRL, + VDCR_HSTART, + VDCR_HEND, + + VDCR_REFRESH +}; + +struct VDC +{ + volatile char addr; + volatile char data; +}; + +#define vdc (*((struct VDC *)0xd600)) + +inline void vdc_reg(VDCRegister reg); + +inline void vdc_write(byte data); + +inline byte vdc_read(void); + + +void vdc_reg_write(VDCRegister reg, byte data); + +byte vdc_reg_read(VDCRegister reg); + + +void vdc_mem_addr(unsigned addr); + +inline void vdc_mem_write(char data); + +inline char vdc_mem_read(void); + + +void vdc_mem_write_at(unsigned addr, char data); + +char vdc_mem_read_at(unsigned addr); + + +void vdc_mem_write_buffer(unsigned addr, const char * data, char size); + +void vdc_mem_read_buffer(unsigned addr, char * data, char size); + + +#pragma compile("vdc.c") + +#endif diff --git a/include/conio.c b/include/conio.c index 4961a5f9..96b711c0 100644 --- a/include/conio.c +++ b/include/conio.c @@ -33,6 +33,33 @@ __asm bsinit sta 0xff01 } #pragma code(code) +#elif defined(__PLUS4__) +#pragma code(lowcode) +__asm bsout +{ + sta 0xff3e + jsr 0xffd2 + sta 0xff3f +} +__asm bsin +{ + sta 0xff3e + jsr 0xffe4 + sta 0xff3f +} +__asm bsplot +{ + sta 0xff3e + jsr 0xfff0 + sta 0xff3f +} +__asm bsinit +{ + sta 0xff3e + jsr 0xff81 + sta 0xff3f +} +#pragma code(code) #else #define bsout 0xffd2 #define bsin 0xffe4 @@ -66,12 +93,25 @@ __asm putpch bcc w3 cmp #123 bcs w3 + +#if defined(__CBMPET__) + cmp #97 + bcs w4 + cmp #91 + bcs w3 + w2: + eor #$a0 + w4: + eor #$20 + +#else cmp #97 bcs w2 cmp #91 bcs w3 w2: eor #$20 +#endif cpx #IOCHM_PETSCII_2 beq w3 and #$df diff --git a/include/crt.c b/include/crt.c index 80014e1f..afb91a7e 100644 --- a/include/crt.c +++ b/include/crt.c @@ -24,6 +24,41 @@ char spentry = 0; int main(void); +#if defined (__PLUS4__) + +#pragma code(lowcode) +__asm p4irqx +{ + sta $ff3f + pla + tax + pla + rti +} + +__asm p4irq +{ + pha + txa + pha + sta $ff3e + + lda #>p4irqx + pha + lda #p4irq + sta $ffff + sta $ff3f #endif tsx @@ -253,7 +294,8 @@ l2: dey #if defined(__C128__) lda #0 sta 0xff00 -#endif +#elif defined(__PLUS4__) + sta $ff3e #endif rts } diff --git a/include/plus4/ted.c b/include/plus4/ted.c new file mode 100644 index 00000000..44c8153d --- /dev/null +++ b/include/plus4/ted.c @@ -0,0 +1,73 @@ +#include "ted.h" + +void ted_waitBottom(void) +{ + while (!(ted.vscan_high & 1)) + ; +} + +void ted_waitTop(void) +{ + while (ted.vscan_high & 1) + ; +} + +void ted_waitFrame(void) +{ + while (ted.vscan_high & 1) + ; + while (!(ted.vscan_high & 1)) + ; +} + +void ted_waitLine(int line) +{ + char upper = (char)(line >> 8) & 1; + char lower = (char)line; + + do + { + while (ted.vscan_low != lower) + ; + } while ((ted.vscan_high & 1) != upper); +} + +void ted_setmode(TedMode mode, char * text, char * font) +{ + switch (mode) + { + case TEDM_TEXT: + ted.ctrl1 = TED_CTRL1_DEN | TED_CTRL1_RSEL | 3; + ted.ctrl2 = TED_CTRL2_CSEL; + break; + case TEDM_TEXT_MC: + ted.ctrl1 = TED_CTRL1_DEN | TED_CTRL1_RSEL | 3; + ted.ctrl2 = TED_CTRL2_CSEL | TED_CTRL2_MCM; + break; + case TEDM_TEXT_ECM: + ted.ctrl1 = TED_CTRL1_DEN | TED_CTRL1_ECM | TED_CTRL1_RSEL | 3; + ted.ctrl2 = TED_CTRL2_CSEL; + break; + case TEDM_HIRES: + ted.ctrl1 = TED_CTRL1_BMM | TED_CTRL1_DEN | TED_CTRL1_RSEL | 3; + ted.ctrl2 = TED_CTRL2_CSEL; + break; + case TEDM_HIRES_MC: + ted.ctrl1 = TED_CTRL1_BMM | TED_CTRL1_DEN | TED_CTRL1_RSEL | 3; + ted.ctrl2 = TED_CTRL2_CSEL | TED_CTRL2_MCM; + break; + default: + __assume(false); + } + + ted.vid_ptr = (unsigned)text >> 8; + + if (mode < TEDM_HIRES) + { + ted.char_ptr = (unsigned)font >> 8; + } + else + { + ted.sound1_high = (ted.sound1_high & 0x3) | ((unsigned)font >> 10); + } +} diff --git a/include/plus4/ted.h b/include/plus4/ted.h new file mode 100644 index 00000000..ba0b0dfd --- /dev/null +++ b/include/plus4/ted.h @@ -0,0 +1,102 @@ +#ifndef PLUS4_TED_H +#define PLUS4_TED_H + +#include + +#define TED_CTRL1_RSEL 0x08 +#define TED_CTRL1_DEN 0x10 +#define TED_CTRL1_BMM 0x20 +#define TED_CTRL1_ECM 0x40 + +#define TED_CTRL2_CSEL 0x08 +#define TED_CTRL2_MCM 0x10 +#define TED_CTRL2_RES 0x20 +#define TED_CTRL2_NTSC 0x40 +#define TED_CTRL2_INV 0x80 + +#define TED_INTR_RST 0x02 +#define TED_INTR_LPEN 0x04 +#define TED_INTR_CNT1 0x08 +#define TED_INTR_CNT2 0x10 +#define TED_INTR_CNT3 0x20 +#define TED_INTR_IRQ 0x80 + +#define TED_SND_SQUARE1 0x10 +#define TES_SND_SQUARE2 0x20 +#define TES_SND_NOISE2 0x40 +#define TES_SND_DA 0x80 + +#define TES_CHAR_ROM 0x04 + +struct TED +{ + volatile word timer0; + volatile word timer1; + + volatile word timer2; + volatile byte ctrl1; + volatile byte ctrl2; + + volatile byte keybin; + volatile byte intr_ctrl; + volatile byte intr_enable; + volatile byte raster; + + volatile word cursor_pos; + volatile byte sound1_low; + volatile byte sound2_low; + + volatile byte sound2_high; + volatile byte sound_ctrl; + volatile byte sound1_high; + volatile byte char_ptr; + + volatile byte vid_ptr; + volatile byte color_back; + volatile byte color_back1; + volatile byte color_back2; + + volatile byte color_back3; + volatile byte color_border; + volatile byte char_pos_high; + volatile byte char_pos_low; + + volatile byte vscan_high; + volatile byte vscan_low; + volatile byte hscan; + volatile byte flash; +}; + +enum TedMode +{ + TEDM_TEXT, + TEDM_TEXT_MC, + TEDM_TEXT_ECM, + TEDM_HIRES, + TEDM_HIRES_MC +}; + +// set the display mode and base address. This will also +// adapt the bank. +void ted_setmode(TedMode mode, char * text, char * font); + +// wait for the beam to reach the bottom of the visual area +inline void ted_waitBottom(void); + +// wait for the beam to reach the top of the frame +inline void ted_waitTop(void); + +// wait for the top of the frame and then for the bottom of the visual area +inline void ted_waitFrame(void); + +// wait for a specific raster line +void ted_waitLine(int line); + + +// reference to the TED chip +#define ted (*((struct TED *)0xff00)) + +#pragma compile("ted.c") + +#endif + diff --git a/include/stdio.c b/include/stdio.c index 0386b368..99cef202 100644 --- a/include/stdio.c +++ b/include/stdio.c @@ -26,6 +26,27 @@ __asm bsin sta 0xff01 } +#pragma code(code) +#elif defined(__PLUS4__) +#pragma code(lowcode) +__asm bsout +{ + sta 0xff3e + jsr 0xffd2 + sta 0xff3f +} +__asm bsin +{ + sta 0xff3e + jsr 0xffe4 + sta 0xff3f +} +__asm bsplot +{ + sta 0xff3e + jsr 0xfff0 + sta 0xff3f +} #pragma code(code) #else #define bsout 0xffd2 @@ -53,12 +74,24 @@ __asm putpch bcc w3 cmp #123 bcs w3 +#if defined(__CBMPET__) + cmp #97 + bcs w4 + cmp #91 + bcs w3 + w2: + eor #$a0 + w4: + eor #$20 + +#else cmp #97 bcs w2 cmp #91 bcs w3 w2: eor #$20 +#endif cpx #IOCHM_PETSCII_2 beq w3 and #$df diff --git a/include/time.c b/include/time.c index 2a1a01a6..0a43255e 100644 --- a/include/time.c +++ b/include/time.c @@ -4,6 +4,25 @@ clock_t clock(void) { __asm { +#if defined(__PLUS4__) + lda $a5 + sta accu + 0 + lda $a4 + sta accu + 1 + lda $a3 + sta accu + 2 + lda #0 + sta accu + 3 +#elif defined(__CBMPET__) + lda $8f + sta accu + 0 + lda $8e + sta accu + 1 + lda $8d + sta accu + 2 + lda #0 + sta accu + 3 +#else lda $a2 sta accu + 0 lda $a1 @@ -12,5 +31,6 @@ clock_t clock(void) sta accu + 2 lda #0 sta accu + 3 +#endif } } diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 02cd6e90..9210ebf1 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -72,15 +72,18 @@ bool Compiler::ParseSource(void) case TMACH_VIC20: case TMACH_VIC20_3K: case TMACH_VIC20_8K: + case TMACH_PET_8K: mCompilationUnits->mSectionStack->mSize = 512; mCompilationUnits->mSectionHeap->mSize = 512; break; + case TMACH_PET_16K: case TMACH_VIC20_16K: case TMACH_VIC20_24K: mCompilationUnits->mSectionStack->mSize = 1024; mCompilationUnits->mSectionHeap->mSize = 1024; break; case TMACH_C128: + case TMACH_PLUS4: mCompilationUnits->mSectionLowCode = mLinker->AddSection(Ident::Unique("lowcode"), LST_DATA); break; case TMACH_NES: @@ -246,6 +249,19 @@ bool Compiler::GenerateCode(void) else regionStartup = mLinker->AddRegion(identStartup, 0x1c01, 0x1d00); break; + case TMACH_PLUS4: + if (mCompilerOptions & COPT_NATIVE) + { + regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080); + regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1100); + } + else + { + regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080); + regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1000); + } + regionLowcode->mSections.Push(mCompilationUnits->mSectionLowCode); + break; case TMACH_VIC20: if (mCompilerOptions & COPT_NATIVE) regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080); @@ -253,6 +269,9 @@ bool Compiler::GenerateCode(void) regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1100); break; case TMACH_VIC20_3K: + case TMACH_PET_8K: + case TMACH_PET_16K: + case TMACH_PET_32K: if (mCompilerOptions & COPT_NATIVE) regionStartup = mLinker->AddRegion(identStartup, 0x0401, 0x0480); else @@ -289,10 +308,14 @@ bool Compiler::GenerateCode(void) case TMACH_C128B: regionBytecode = mLinker->AddRegion(identBytecode, 0x1d00, 0x1e00); break; + case TMACH_PLUS4: case TMACH_VIC20: regionBytecode = mLinker->AddRegion(identBytecode, 0x1100, 0x1200); break; case TMACH_VIC20_3K: + case TMACH_PET_8K: + case TMACH_PET_16K: + case TMACH_PET_32K: regionBytecode = mLinker->AddRegion(identBytecode, 0x0500, 0x0600); break; case TMACH_VIC20_8K: @@ -348,6 +371,9 @@ bool Compiler::GenerateCode(void) case TMACH_C128B: regionMain = mLinker->AddRegion(identMain, 0x1e00, 0x4000); break; + case TMACH_PLUS4: + regionMain = mLinker->AddRegion(identMain, 0x1200, 0xfc00); + break; case TMACH_VIC20: regionMain = mLinker->AddRegion(identMain, 0x1200, 0x1e00); break; @@ -363,6 +389,15 @@ bool Compiler::GenerateCode(void) case TMACH_VIC20_24K: regionMain = mLinker->AddRegion(identMain, 0x1400, 0x8000); break; + case TMACH_PET_8K: + regionMain = mLinker->AddRegion(identMain, 0x0600, 0x2000); + break; + case TMACH_PET_16K: + regionMain = mLinker->AddRegion(identMain, 0x0600, 0x4000); + break; + case TMACH_PET_32K: + regionMain = mLinker->AddRegion(identMain, 0x0600, 0x8000); + break; } } else @@ -378,6 +413,9 @@ bool Compiler::GenerateCode(void) case TMACH_C128B: regionMain = mLinker->AddRegion(identMain, 0x1c80, 0x4000); break; + case TMACH_PLUS4: + regionMain = mLinker->AddRegion(identMain, 0x1100, 0xfc00); + break; case TMACH_VIC20: regionMain = mLinker->AddRegion(identMain, 0x1080, 0x1e00); break; @@ -393,6 +431,15 @@ bool Compiler::GenerateCode(void) case TMACH_VIC20_24K: regionMain = mLinker->AddRegion(identMain, 0x1280, 0x8000); break; + case TMACH_PET_8K: + regionMain = mLinker->AddRegion(identMain, 0x0480, 0x2000); + break; + case TMACH_PET_16K: + regionMain = mLinker->AddRegion(identMain, 0x0480, 0x4000); + break; + case TMACH_PET_32K: + regionMain = mLinker->AddRegion(identMain, 0x0480, 0x8000); + break; } } } diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 1d262cff..f6f1105c 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -48,6 +48,10 @@ enum TargetMachine TMACH_VIC20_24K, TMACH_C128, TMACH_C128B, + TMACH_PET_8K, + TMACH_PET_16K, + TMACH_PET_32K, + TMACH_PLUS4, TMACH_NES }; diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index b4ec0822..1bf64b18 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -282,6 +282,30 @@ int main2(int argc, const char** argv) compiler->mTargetMachine = TMACH_VIC20_24K; compiler->AddDefine(Ident::Unique("__VIC20__"), "1"); } + else if (!strcmp(targetMachine, "pet")) + { + strcpy_s(basicStart, "0x0401"); + compiler->mTargetMachine = TMACH_PET_8K; + compiler->AddDefine(Ident::Unique("__CBMPET__"), "1"); + } + else if (!strcmp(targetMachine, "pet16")) + { + strcpy_s(basicStart, "0x0401"); + compiler->mTargetMachine = TMACH_PET_16K; + compiler->AddDefine(Ident::Unique("__CBMPET__"), "1"); + } + else if (!strcmp(targetMachine, "pet32")) + { + strcpy_s(basicStart, "0x0401"); + compiler->mTargetMachine = TMACH_PET_32K; + compiler->AddDefine(Ident::Unique("__CBMPET__"), "1"); + } + else if (!strcmp(targetMachine, "plus4")) + { + strcpy_s(basicStart, "0x1001"); + compiler->mTargetMachine = TMACH_PLUS4; + compiler->AddDefine(Ident::Unique("__PLUS4__"), "1"); + } else if (!strcmp(targetMachine, "nes")) { compiler->mTargetMachine = TMACH_NES;