From 08b25e610d95fda8cb31dee2be886215861fc0c5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 26 Aug 2020 19:34:12 +0200 Subject: [PATCH] commander x16 improvements --- compiler/res/prog8lib/c64lib.p8 | 12 +- compiler/res/prog8lib/cx16lib.p8 | 142 ++++++++++++++++-- compiler/res/prog8lib/cx16utils.p8 | 40 ++--- compiler/src/prog8/CompilerMain.kt | 2 +- .../target/cx16/CX16MachineDefinition.kt | 8 +- examples/test.p8 | 67 ++++++--- 6 files changed, 207 insertions(+), 64 deletions(-) diff --git a/compiler/res/prog8lib/c64lib.p8 b/compiler/res/prog8lib/c64lib.p8 index ac81b1eb5..73a25a30b 100644 --- a/compiler/res/prog8lib/c64lib.p8 +++ b/compiler/res/prog8lib/c64lib.p8 @@ -174,19 +174,11 @@ c64 { ; ---- end of SID registers ---- - -; ---- C64 basic routines ---- - -romsub $E544 = CLEARSCR() clobbers(A,X,Y) ; clear the screen -romsub $E566 = HOMECRSR() clobbers(A,X,Y) ; cursor to top left of screen - - -; ---- end of C64 basic routines ---- - - ; ---- C64 kernal routines ---- romsub $AB1E = STROUT(uword strptr @ AY) clobbers(A, X, Y) ; print null-terminated string (use c64scr.print instead) +romsub $E544 = CLEARSCR() clobbers(A,X,Y) ; clear the screen +romsub $E566 = HOMECRSR() clobbers(A,X,Y) ; cursor to top left of screen romsub $EA31 = IRQDFRT() clobbers(A,X,Y) ; default IRQ routine romsub $EA81 = IRQDFEND() clobbers(A,X,Y) ; default IRQ end/cleanup romsub $FF81 = CINT() clobbers(A,X,Y) ; (alias: SCINIT) initialize screen editor and video chip diff --git a/compiler/res/prog8lib/cx16lib.p8 b/compiler/res/prog8lib/cx16lib.p8 index c636eb8d0..6a704170d 100644 --- a/compiler/res/prog8lib/cx16lib.p8 +++ b/compiler/res/prog8lib/cx16lib.p8 @@ -6,9 +6,13 @@ ; indent format: TABS, size=8 -cx16 { +c64 { -; ---- C64 kernal routines ---- +; ---- kernal routines, these are the same as on the Commodore-64 (hence the same block name) ---- + +; STROUT --> use screen.print +; CLEARSCR -> use screen.clear_screen +; HOMECRSR -> use screen.plot romsub $FF81 = CINT() clobbers(A,X,Y) ; (alias: SCINIT) initialize screen editor and video chip romsub $FF84 = IOINIT() clobbers(A, X) ; initialize I/O devices (CIA, SID, IRQ) @@ -47,9 +51,125 @@ romsub $FFE4 = GETIN() clobbers(X,Y) -> ubyte @ A ; (via 810 ($32A romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns -romsub $FFF0 = PLOT(ubyte col @ Y, ubyte row @ X, ubyte dir @ Pc) -> ubyte @ X, ubyte @ Y ; read/set position of cursor on screen. Use c64scr.plot for a 'safe' wrapper that preserves X. +romsub $FFF0 = PLOT(ubyte col @ Y, ubyte row @ X, ubyte dir @ Pc) -> ubyte @ X, ubyte @ Y ; read/set position of cursor on screen. Use screen.plot for a 'safe' wrapper that preserves X. romsub $FFF3 = IOBASE() -> uword @ XY ; read base address of I/O devices +} + +cx16 { + +; ---- Commander X-16 additions on top of C64 kernal routines ---- +; spelling of the names is taken from the Commander X-16 rom sources + +; the sixteen virtual 16-bit registers +&ubyte r0 = $02 +&ubyte r0L = $02 +&ubyte r0H = $03 +&ubyte r1 = $04 +&ubyte r1L = $04 +&ubyte r1H = $05 +&ubyte r2 = $06 +&ubyte r2L = $06 +&ubyte r2H = $07 +&ubyte r3 = $08 +&ubyte r3L = $08 +&ubyte r3H = $09 +&ubyte r4 = $0a +&ubyte r4L = $0a +&ubyte r4H = $0b +&ubyte r5 = $0c +&ubyte r5L = $0c +&ubyte r5H = $0d +&ubyte r6 = $0e +&ubyte r6L = $0e +&ubyte r6H = $0f +&ubyte r7 = $10 +&ubyte r7L = $10 +&ubyte r7H = $11 +&ubyte r8 = $12 +&ubyte r8L = $12 +&ubyte r8H = $13 +&ubyte r9 = $14 +&ubyte r9L = $14 +&ubyte r9H = $15 +&ubyte r10 = $16 +&ubyte r10L = $16 +&ubyte r10H = $17 +&ubyte r11 = $18 +&ubyte r11L = $18 +&ubyte r11H = $19 +&ubyte r12 = $1a +&ubyte r12L = $1a +&ubyte r12H = $1b +&ubyte r13 = $1c +&ubyte r13L = $1c +&ubyte r13H = $1d +&ubyte r14 = $1e +&ubyte r14L = $1e +&ubyte r14H = $1f +&ubyte r15 = $20 +&ubyte r15L = $20 +&ubyte r15H = $21 + + +; TODO subroutine args + soubroutine returnvalues + clobber registers + +; supported C128 additions +romsub $ff4a = close_all() +romsub $ff59 = lkupla() +romsub $ff5c = lkupsa() +romsub $ff5f = screen_set_mode() +romsub $ff62 = dlchr() +romsub $ff65 = pfkey() +romsub $ff6e = jsrfar() +romsub $ff74 = fetch() +romsub $ff77 = stash() +romsub $ff7a = cmpare() +romsub $ff7d = primm() + +; X16 additions +romsub $ff44 = macptr() +romsub $ff47 = enter_basic() +romsub $ff68 = mouse_config() +romsub $ff6b = mouse_get() +romsub $ff71 = mouse_scan() +romsub $ff53 = joystick_scan() +romsub $ff56 = joystick_get() +romsub $ff4d = clock_set_date_time() +romsub $ff50 = clock_get_date_time() + +; high level graphics & fonts +romsub $ff20 = GRAPH_init() +romsub $ff23 = GRAPH_clear() +romsub $ff26 = GRAPH_set_window() +romsub $ff29 = GRAPH_set_colors() +romsub $ff2c = GRAPH_draw_line() +romsub $ff2f = GRAPH_draw_rect() +romsub $ff32 = GRAPH_move_rect() +romsub $ff35 = GRAPH_draw_oval() +romsub $ff38 = GRAPH_draw_image() +romsub $ff3b = GRAPH_set_font() +romsub $ff3e = GRAPH_get_char_size() +romsub $ff41 = GRAPH_put_char() + +; framebuffer API not yet included. + +romsub $fef0 = sprite_set_image() +romsub $fef3 = sprite_set_position() +romsub $fee4 = memory_fill() +romsub $fee7 = memory_copy() +romsub $feea = memory_crc() +romsub $feed = memory_decompress() +romsub $fedb = console_init() +romsub $fede = console_put_char() +romsub $fee1 = console_get_char() +romsub $fed8 = console_put_image() +romsub $fed5 = console_set_paging_message() +romsub $fed2 = kbdbuf_put() +romsub $fecf = entropy_get() +romsub $fecc = monitor() + + ; ---- end of kernal routines ---- @@ -59,19 +179,21 @@ asmsub init_system() { %asm {{ sei cld - ;lda #%00101111 - ;sta $00 - ;lda #%00100111 - ;sta $01 - jsr cx16.IOINIT - jsr cx16.RESTOR - jsr cx16.CINT + lda #0 + sta $00 + sta $01 + jsr c64.IOINIT + jsr c64.RESTOR + jsr c64.CINT lda #0 tax tay clc clv cli + lda #66 + clc + jsr console_put_char rts }} } diff --git a/compiler/res/prog8lib/cx16utils.p8 b/compiler/res/prog8lib/cx16utils.p8 index 72716f5c0..f0b1652e7 100644 --- a/compiler/res/prog8lib/cx16utils.p8 +++ b/compiler/res/prog8lib/cx16utils.p8 @@ -387,14 +387,14 @@ asmsub print (str text @ AY) clobbers(A,Y) { ; ---- print null terminated string from A/Y ; note: the compiler contains an optimization that will replace ; a call to this subroutine with a string argument of just one char, - ; by just one call to cx16.CHROUT of that single char. + ; by just one call to c64.CHROUT of that single char. %asm {{ sta P8ZP_SCRATCH_B1 sty P8ZP_SCRATCH_REG ldy #0 - lda (P8ZP_SCRATCH_B1),y beq + - jsr cx16.CHROUT + jsr c64.CHROUT iny bne - + rts @@ -408,11 +408,11 @@ asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) { jsr cx16utils.ubyte2decimal pha tya - jsr cx16.CHROUT + jsr c64.CHROUT pla - jsr cx16.CHROUT + jsr c64.CHROUT txa - jsr cx16.CHROUT + jsr c64.CHROUT ldx P8ZP_SCRATCH_REG_X rts }} @@ -428,16 +428,16 @@ _print_byte_digits cpy #'0' beq + tya - jsr cx16.CHROUT + jsr c64.CHROUT pla - jsr cx16.CHROUT + jsr c64.CHROUT jmp _ones + pla cmp #'0' beq _ones - jsr cx16.CHROUT + jsr c64.CHROUT _ones txa - jsr cx16.CHROUT + jsr c64.CHROUT ldx P8ZP_SCRATCH_REG_X rts }} @@ -451,7 +451,7 @@ asmsub print_b (byte value @ A) clobbers(A,Y) { cmp #0 bpl + lda #'-' - jsr cx16.CHROUT + jsr c64.CHROUT + pla jsr cx16utils.byte2decimal jsr print_ub._print_byte_digits @@ -467,12 +467,12 @@ asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) { bcc + pha lda #'$' - jsr cx16.CHROUT + jsr c64.CHROUT pla + jsr cx16utils.ubyte2hex - jsr cx16.CHROUT + jsr c64.CHROUT tya - jsr cx16.CHROUT + jsr c64.CHROUT ldx P8ZP_SCRATCH_REG_X rts }} @@ -485,13 +485,13 @@ asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) { sta P8ZP_SCRATCH_B1 bcc + lda #'%' - jsr cx16.CHROUT + jsr c64.CHROUT + ldy #8 - lda #'0' asl P8ZP_SCRATCH_B1 bcc + lda #'1' -+ jsr cx16.CHROUT ++ jsr c64.CHROUT dey bne - ldx P8ZP_SCRATCH_REG_X @@ -532,7 +532,7 @@ asmsub print_uw0 (uword value @ AY) clobbers(A,Y) { ldy #0 - lda cx16utils.uword2decimal.decTenThousands,y beq + - jsr cx16.CHROUT + jsr c64.CHROUT iny bne - + ldx P8ZP_SCRATCH_REG_X @@ -555,14 +555,14 @@ asmsub print_uw (uword value @ AY) clobbers(A,Y) { bne - _gotdigit - jsr cx16.CHROUT + jsr c64.CHROUT iny lda cx16utils.uword2decimal.decTenThousands,y bne _gotdigit rts _allzero lda #'0' - jmp cx16.CHROUT + jmp c64.CHROUT }} } @@ -573,7 +573,7 @@ asmsub print_w (word value @ AY) clobbers(A,Y) { bpl + pha lda #'-' - jsr cx16.CHROUT + jsr c64.CHROUT tya eor #255 tay @@ -593,7 +593,7 @@ asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) { stx P8ZP_SCRATCH_REG_X tax clc - jsr cx16.PLOT + jsr c64.PLOT ldx P8ZP_SCRATCH_REG_X rts }} diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index d1e4f973d..de61eafad 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -41,7 +41,7 @@ private fun compileMain(args: Array) { val dontWriteAssembly by cli.flagArgument("-noasm", "don't create assembly code") val dontOptimize by cli.flagArgument("-noopt", "don't perform any optimizations") val watchMode by cli.flagArgument("-watch", "continuous compilation mode (watches for file changes), greatly increases compilation speed") - val compilationTarget by cli.flagValueArgument("-target", "compilertarget", "target output of the compiler, currently only 'c64' (C64 6502 assembly) available", "c64") + val compilationTarget by cli.flagValueArgument("-target", "compilertarget", "target output of the compiler, currently 'c64' and 'cx16' available", "c64") val moduleFiles by cli.positionalArgumentsList("modules", "main module file(s) to compile", minArgs = 1) try { diff --git a/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt b/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt index 9c7a62543..103a5c186 100644 --- a/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt +++ b/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt @@ -92,18 +92,20 @@ internal object CX16MachineDefinition: IMachineDefinition { if (options.floats && options.zeropage !in setOf(ZeropageType.BASICSAFE, ZeropageType.DONTUSE )) throw CompilerException("when floats are enabled, zero page type should be 'basicsafe' or 'dontuse'") + // the addresses 0x02 to 0x21 (inclusive) are taken for sixteen virtual 16-bit api registers. + when (options.zeropage) { ZeropageType.FULL -> { - free.addAll(0x02..0xff) + free.addAll(0x22..0xff) free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) } ZeropageType.KERNALSAFE -> { - free.addAll(0x02..0x7f) + free.addAll(0x22..0x7f) free.addAll(0xa9..0xff) free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) } ZeropageType.BASICSAFE -> { - free.addAll(0x02..0x7f) + free.addAll(0x22..0x7f) free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) } ZeropageType.DONTUSE -> { diff --git a/examples/test.p8 b/examples/test.p8 index 7f02106d1..119608e87 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,28 +4,55 @@ main { sub start() { - uword xx = $ef34 + cx16.r0L = 2020 - 1900 + cx16.r0H = 8 + cx16.r1L = 26 + cx16.r1H = 19 + cx16.r2L = 16 + cx16.r2H = 0 + cx16.r3L = 0 + cx16.clock_set_date_time() + c64.CHROUT(14) ; lowercase charset - xx &= $00f0 - screen.print_uwhex(xx, 1) - cx16.CHROUT('\n') - xx |= $000f - screen.print_uwhex(xx, 1) - cx16.CHROUT('\n') - xx ^= $0011 - screen.print_uwhex(xx, 1) - cx16.CHROUT('\n') + repeat { + c64.CHROUT(19) ; HOME + screen.print(" yyyy-mm-dd HH:MM:SS.jj\n\n") + cx16.clock_get_date_time() + c64.CHROUT(' ') + print_date() + c64.CHROUT(' ') + print_time() + } + } - xx = $ef34 - xx &= $f000 - screen.print_uwhex(xx, 1) - cx16.CHROUT('\n') - xx |= $0f00 - screen.print_uwhex(xx, 1) - cx16.CHROUT('\n') - xx ^= $1100 - screen.print_uwhex(xx, 1) - cx16.CHROUT('\n') + sub print_date() { + screen.print_uw(1900 + cx16.r0L) + c64.CHROUT('-') + if cx16.r0H < 10 + c64.CHROUT('0') + screen.print_ub(cx16.r0H) + c64.CHROUT('-') + if cx16.r1L < 10 + c64.CHROUT('0') + screen.print_ub(cx16.r1L) + } + + sub print_time() { + if cx16.r1H < 10 + c64.CHROUT('0') + screen.print_ub(cx16.r1H) + c64.CHROUT(':') + if cx16.r2L < 10 + c64.CHROUT('0') + screen.print_ub(cx16.r2L) + c64.CHROUT(':') + if cx16.r2H < 10 + c64.CHROUT('0') + screen.print_ub(cx16.r2H) + c64.CHROUT('.') + if cx16.r3L < 10 + c64.CHROUT('0') + screen.print_ub(cx16.r3L) } }