From fc33ab89054e29e6d76970584237daff10c23c4e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 24 Dec 2021 00:08:32 +0100 Subject: [PATCH] shuffled some system functions back to c64 block to remain compatible with existing code, added missing float and graphics library stubs --- compiler/res/prog8lib/c128/floats.p8 | 163 +++++++++++++++++++++++++ compiler/res/prog8lib/c128/graphics.p8 | 60 +++++++++ compiler/res/prog8lib/c128/syslib.p8 | 142 ++++++++++----------- 3 files changed, 295 insertions(+), 70 deletions(-) create mode 100644 compiler/res/prog8lib/c128/floats.p8 create mode 100644 compiler/res/prog8lib/c128/graphics.p8 diff --git a/compiler/res/prog8lib/c128/floats.p8 b/compiler/res/prog8lib/c128/floats.p8 new file mode 100644 index 000000000..48b10818f --- /dev/null +++ b/compiler/res/prog8lib/c128/floats.p8 @@ -0,0 +1,163 @@ +; Prog8 definitions for floating point handling on the Commodore 128 +; +; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 + +%option enable_floats + +floats { + ; ---- this block contains C-128 compatible floating point related functions ---- + + const float PI = 3.141592653589793 + const float TWOPI = 6.283185307179586 + + float tempvar_swap_float ; used for some swap() operations + + +; ---- ROM float functions ---- + +; TODO c128 fix float routine addresses + + ; note: the fac1 and fac2 are working registers and take 6 bytes each, + ; floats in memory (and rom) are stored in 5-byte MFLPT packed format. + +; note: fac1/2 might get clobbered even if not mentioned in the function's name. +; note: for subtraction and division, the left operand is in fac2, the right operand in fac1. + +romsub $fe00 = AYINT() clobbers(A,X,Y) ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) + +; GIVAYF: signed word in Y/A (note different lsb/msb order) -> float in fac1 +; there is also floats.GIVUAYFAY - unsigned word in A/Y (lo/hi) to fac1 +; (tip: use GIVAYFAY to use A/Y input; lo/hi switched to normal order) +romsub $fe03 = GIVAYF(ubyte lo @ Y, ubyte hi @ A) clobbers(A,X,Y) + +; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15) +; (tip: use GETADRAY to get A/Y output; lo/hi switched to normal little endian order) +romsub $fe06 = GETADR() clobbers(X) -> ubyte @ Y, ubyte @ A + +romsub $fe09 = FADDH() clobbers(A,X,Y) ; fac1 += 0.5, for rounding- call this before INT +romsub $fe0c = FSUB(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 = mflpt from A/Y - fac1 +romsub $fe0f = FSUBT() clobbers(A,X,Y) ; fac1 = fac2-fac1 mind the order of the operands +romsub $fe12 = FADD(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 += mflpt value from A/Y +romsub $fe15 = FADDT() clobbers(A,X,Y) ; fac1 += fac2 +romsub $fe1b = ZEROFC() clobbers(A,X,Y) ; fac1 = 0 +romsub $fe1e = NORMAL() clobbers(A,X,Y) ; normalize fac1 (?) +romsub $fe24 = LOG() clobbers(A,X,Y) ; fac1 = LN(fac1) (natural log) +romsub $fe27 = FMULT(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 *= mflpt value from A/Y +romsub $fe2a = FMULTT() clobbers(A,X,Y) ; fac1 *= fac2 +romsub $fe30 = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2 +romsub $fe33 = MUL10() clobbers(A,X,Y) ; fac1 *= 10 +romsub $fe36 = DIV10() clobbers(A,X,Y) ; fac1 /= 10 , CAUTION: result is always positive! +romsub $fe39 = FDIV(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 = mflpt in A/Y / fac1 (remainder in fac2) +romsub $fe3c = FDIVT() clobbers(A,X,Y) ; fac1 = fac2/fac1 (remainder in fac2) mind the order of the operands + +romsub $fe42 = MOVFM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 +romsub $fe45 = MOVMF(uword mflpt @ XY) clobbers(A,X,Y) ; store fac1 to memory X/Y as 5-byte mflpt +romsub $fe48 = MOVFA() clobbers(A,X) ; copy fac2 to fac1 +romsub $fe4b = MOVAF() clobbers(A,X) ; copy fac1 to fac2 (rounded) +romsub $fe4e = MOVEF() clobbers(A,X) ; copy fac1 to fac2 +romsub $fe54 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive +romsub $fe57 = SGN() clobbers(A,X,Y) ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) +romsub $fe5a = FREADSA(byte value @ A) clobbers(A,X,Y) ; 8 bit signed A -> float in fac1 +romsub $fe66 = ABS() clobbers(A,X,Y) ; fac1 = ABS(fac1) +romsub $fe69 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than +romsub $fe72 = INT() clobbers(A,X,Y) ; INT() truncates, use FADDH first to round instead of trunc +romsub $fe78 = FINLOG(byte value @A) clobbers (A, X, Y) ; fac1 += signed byte in A +romsub $fe7b = FOUT() clobbers(X) -> uword @ AY ; fac1 -> string, address returned in AY +romsub $fe81 = SQR() clobbers(A,X,Y) ; fac1 = SQRT(fac1) +romsub $fe84 = FPWRT() clobbers(A,X,Y) ; fac1 = fac2 ** fac1 +romsub $fe8a = NEGOP() clobbers(A) ; switch the sign of fac1 (fac1 = -fac1) +romsub $fe8d = EXP() clobbers(A,X,Y) ; fac1 = EXP(fac1) (e ** fac1) +romsub $fe96 = RND() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator +romsub $fe99 = COS() clobbers(A,X,Y) ; fac1 = COS(fac1) +romsub $fe9c = SIN() clobbers(A,X,Y) ; fac1 = SIN(fac1) +romsub $fe9f = TAN() clobbers(A,X,Y) ; fac1 = TAN(fac1) +romsub $fea2 = ATN() clobbers(A,X,Y) ; fac1 = ATN(fac1) + + +asmsub GIVUAYFAY (uword value @ AY) clobbers(A,X,Y) { + ; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1 + %asm {{ + stx P8ZP_SCRATCH_REG + sta _tmp + sty P8ZP_SCRATCH_B1 + tya + ldy _tmp + jsr GIVAYF ; load it as signed... correct afterwards + lda P8ZP_SCRATCH_B1 + bpl + + lda #<_flt65536 + ldy #>_flt65536 + jsr FADD ++ ldx P8ZP_SCRATCH_REG + rts +_tmp .byte 0 +_flt65536 .byte 145,0,0,0,0 ; 65536.0 + }} +} + + +asmsub GIVAYFAY (uword value @ AY) clobbers(A,X,Y) { + ; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1 + %asm {{ + sta P8ZP_SCRATCH_B1 + tya + ldy P8ZP_SCRATCH_B1 + jmp GIVAYF ; this uses the inverse order, Y/A + }} +} + +asmsub FTOSWRDAY () clobbers(X) -> uword @ AY { + ; ---- fac1 to signed word in A/Y + %asm {{ + jsr FTOSWORDYA ; note the inverse Y/A order + sta P8ZP_SCRATCH_B1 + tya + ldy P8ZP_SCRATCH_B1 + rts + }} +} + +asmsub GETADRAY () clobbers(X) -> uword @ AY { + ; ---- fac1 to unsigned word in A/Y + %asm {{ + jsr GETADR ; this uses the inverse order, Y/A + sta P8ZP_SCRATCH_B1 + tya + ldy P8ZP_SCRATCH_B1 + rts + }} +} + +asmsub FREADUY (ubyte value @Y) { + ; -- 8 bit unsigned Y -> float in fac1 + %asm {{ + lda #0 + jmp GIVAYF + }} +} + +sub print_f (float value) { + ; ---- prints the floating point value (without a newline). + %asm {{ + stx P8ZP_SCRATCH_REG + lda #value + jsr MOVFM ; load float into fac1 + jsr FOUT ; fac1 to string in A/Y + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy #0 +- lda (P8ZP_SCRATCH_W1),y + beq + + jsr c64.CHROUT + iny + bne - ++ ldx P8ZP_SCRATCH_REG + rts + }} +} + +%asminclude "library:c64/floats.asm" +%asminclude "library:c64/floats_funcs.asm" + +} diff --git a/compiler/res/prog8lib/c128/graphics.p8 b/compiler/res/prog8lib/c128/graphics.p8 new file mode 100644 index 000000000..589d3f02c --- /dev/null +++ b/compiler/res/prog8lib/c128/graphics.p8 @@ -0,0 +1,60 @@ +%import syslib +%import textio + +; Bitmap pixel graphics module for the Commodore 128 + +; TODO c128 actually implement the graphics routines. Ideally a way to 'borrow' the code form the C64 version without just copy-pasting that here? + +graphics { + const uword WIDTH = 320 + const ubyte HEIGHT = 200 + + sub enable_bitmap_mode() { + ; enable bitmap screen, erase it and set colors to black/white. + ; TODO + } + + sub disable_bitmap_mode() { + ; enables text mode, erase the text screen, color white + ; TODO + } + + + sub clear_screen(ubyte pixelcolor, ubyte bgcolor) { + ; TODO + } + + sub line(uword @zp x1, ubyte @zp y1, uword @zp x2, ubyte @zp y2) { + ; TODO + } + + sub fillrect(uword x, uword y, uword width, uword height) { + ; TODO + } + + sub rect(uword x, uword y, uword width, uword height) { + ; TODO + } + + sub horizontal_line(uword x, uword y, uword length) { + ; TODO + } + + sub vertical_line(uword x, uword y, uword height) { + ; TODO + } + + sub circle(uword xcenter, ubyte ycenter, ubyte radius) { + ; TODO + } + + sub disc(uword xcenter, ubyte ycenter, ubyte radius) { + ; TODO + } + + inline asmsub plot(uword plotx @R0, uword ploty @R1) clobbers(A, X, Y) { + %asm {{ + nop ; TODO + }} + } +} diff --git a/compiler/res/prog8lib/c128/syslib.p8 b/compiler/res/prog8lib/c128/syslib.p8 index b149ae8a1..892c13d24 100644 --- a/compiler/res/prog8lib/c128/syslib.p8 +++ b/compiler/res/prog8lib/c128/syslib.p8 @@ -262,56 +262,8 @@ asmsub RDTIM16() -> uword @AY { }} } -} - -c128 { -; ---- C128 specific registers ---- - - &ubyte VM1 = $0A2C ; shadow for VUC $d018 in text mode - &ubyte VM2 = $0A2D ; shadow for VIC $d018 in bitmap screen mode - &ubyte VM3 = $0A2E ; starting page for VDC screen mem - &ubyte VM4 = $0A2F ; starting page for VDC attribute mem - - -; ---- C128 specific system utility routines: ---- - -asmsub init_system() { - ; Initializes the machine to a sane starting state. - ; Called automatically by the loader program logic. - ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, - ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. - ; Also a different color scheme is chosen to identify ourselves a little. - ; Uppercase charset is activated, and all three registers set to 0, status flags cleared. - %asm {{ - sei - cld - ;;lda #%00101111 ; TODO c128 ram and rom bank selection how? - ;;sta $00 - ;;lda #%00100111 - ;;sta $01 - jsr c64.IOINIT - jsr c64.RESTOR - jsr c64.CINT - lda #6 - sta c64.EXTCOL - lda #7 - sta c64.COLOR - lda #0 - sta c64.BGCOL0 - jsr disable_runstop_and_charsetswitch - clc - clv - cli - rts - }} -} - -asmsub init_system_phase2() { - %asm {{ - rts ; no phase 2 steps on the C128 - }} -} +; ---- system utility routines that are essentially the same as on the C64: ----- asmsub disable_runstop_and_charsetswitch() clobbers(A) { %asm {{ lda #$80 @@ -322,27 +274,6 @@ asmsub disable_runstop_and_charsetswitch() clobbers(A) { }} } -asmsub disable_basic() clobbers(A) { - %asm {{ - lda $0a04 ; disable BASIC shadow registers - and #$fe - sta $0a04 - - lda #$01 ; disable BASIC IRQ service routine - sta $12fd - - lda #$ff ; disable screen editor IRQ setup - sta $d8 - - lda #$b7 ; skip programmable function key check - sta $033c - - lda #$0e ; bank out BASIC ROM - sta $ff00 - rts - }} -} - asmsub set_irq(uword handler @AY, ubyte useKernal @Pc) clobbers(A) { %asm {{ sta _modified+1 @@ -500,6 +431,77 @@ _setup_raster_irq }} } +} + +c128 { +; ---- C128 specific registers ---- + + &ubyte VM1 = $0A2C ; shadow for VUC $d018 in text mode + &ubyte VM2 = $0A2D ; shadow for VIC $d018 in bitmap screen mode + &ubyte VM3 = $0A2E ; starting page for VDC screen mem + &ubyte VM4 = $0A2F ; starting page for VDC attribute mem + + +; ---- C128 specific system utility routines: ---- + +asmsub init_system() { + ; Initializes the machine to a sane starting state. + ; Called automatically by the loader program logic. + ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, + ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. + ; Also a different color scheme is chosen to identify ourselves a little. + ; Uppercase charset is activated, and all three registers set to 0, status flags cleared. + %asm {{ + sei + cld + ;;lda #%00101111 ; TODO c128 ram and rom bank selection how? + ;;sta $00 + ;;lda #%00100111 + ;;sta $01 + jsr c64.IOINIT + jsr c64.RESTOR + jsr c64.CINT + lda #6 + sta c64.EXTCOL + lda #7 + sta c64.COLOR + lda #0 + sta c64.BGCOL0 + jsr c64.disable_runstop_and_charsetswitch + clc + clv + cli + rts + }} +} + +asmsub init_system_phase2() { + %asm {{ + rts ; no phase 2 steps on the C128 + }} +} + +asmsub disable_basic() clobbers(A) { + %asm {{ + lda $0a04 ; disable BASIC shadow registers + and #$fe + sta $0a04 + + lda #$01 ; disable BASIC IRQ service routine + sta $12fd + + lda #$ff ; disable screen editor IRQ setup + sta $d8 + + lda #$b7 ; skip programmable function key check + sta $033c + + lda #$0e ; bank out BASIC ROM + sta $ff00 + rts + }} +} + ; ---- end of C128 specific system utility routines ---- }