mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-24 08:02:27 +00:00
c64: fixed issue #203, added openroms-compatible cc65 library overrides for _cgetc and PLOT
This commit is contained in:
1 parent
3e462b0bcd
commit
e32e731612
6 files changed
+144
-4
No files matched your search
+5
-2
@@ -28,8 +28,6 @@ export class C64_WASMMachine extends BaseWASMMachine
|
||||
lightpen_y = 0;
|
||||
|
||||
loadBIOS(srcArray: Uint8Array) {
|
||||
var patch1ofs = 0xea24 - 0xe000 + 0x3000;
|
||||
if (srcArray[patch1ofs] == 0xc4) srcArray[patch1ofs] = 0x60; // cursor move, KIL -> RTS
|
||||
super.loadBIOS(srcArray);
|
||||
}
|
||||
reset() {
|
||||
@@ -79,6 +77,11 @@ export class C64_WASMMachine extends BaseWASMMachine
|
||||
for (var i=0; i<100000 && this.getPC() != this.prgstart; i++) {
|
||||
this.exports.machine_tick(this.sys);
|
||||
}
|
||||
// release RETURN key
|
||||
// (otherwise it stays stuck down and every keyboard read returns CR,
|
||||
// e.g. conio cgetc() always returning a bogus char - GH issue #203)
|
||||
this.exports.machine_key_up(this.sys, 13);
|
||||
this.exports.machine_exec(this.sys, 1); // chips/kbd.c has a "sticky counter"
|
||||
} else {
|
||||
// get out of reset
|
||||
this.exports.machine_exec(this.sys, 100);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Rebuild the Open ROMs compatibility object for cc65 on C64.
|
||||
#
|
||||
# openroms-compat.o - linked before c64.lib (see src/worker/platforms.ts,
|
||||
# libargs for the 'c64' platform) so it overrides
|
||||
# cc65 runtime routines that depend on KERNAL entry
|
||||
# points not implemented by the Open ROMs BIOS:
|
||||
# _cgetc (KBDREAD $E5B4)
|
||||
# PLOT ($FFF0 / UPDCRAMPTR $EA24)
|
||||
|
||||
all: openroms-compat.o
|
||||
|
||||
openroms-compat.o: openroms-compat.s
|
||||
ca65 -I /Users/sehugg/8bitworkshop-compilers/cc65/asminc openroms-compat.s
|
||||
Binary file not shown.
@@ -0,0 +1,123 @@
|
||||
;
|
||||
; Open ROMs compatibility overrides for the cc65 runtime library.
|
||||
;
|
||||
; The Open ROMs KERNAL used by 8bitworkshop is not binary-compatible
|
||||
; with the original Commodore KERNAL at some undocumented entry points
|
||||
; that cc65 routines call directly. This object is linked before
|
||||
; c64.lib so ld65 resolves the overridden symbols here and never pulls
|
||||
; the incompatible library members (cgetc.o, kplot.o).
|
||||
;
|
||||
; Only entry points that are actually broken in Open ROMs are
|
||||
; overridden; everything else (CLRSCR $E544, SCREEN $FFED, BSOUT,
|
||||
; etc.) works and is left to the KERNAL.
|
||||
;
|
||||
; Safe to use with the original C64 KERNAL as well: _cgetc only
|
||||
; depends on the documented keyboard buffer interface (KEY_COUNT /
|
||||
; KEY_BUF), and PLOT is a pure RAM-pointer implementation.
|
||||
;
|
||||
|
||||
.export _cgetc
|
||||
.export PLOT
|
||||
|
||||
.include "c64.inc"
|
||||
|
||||
KEY_BUF := $0277 ; keyboard buffer (10 bytes, FIFO)
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; char cgetc (void)
|
||||
;
|
||||
; cc65's stock version jumps to KBDREAD ($E5B4), which is "get character from
|
||||
; keyboard buffer" on the original KERNAL but unimplemented VIC-II init code
|
||||
; inside Open ROMs - so cgetc() returned garbage instead of blocking/reading.
|
||||
; Read the buffer directly instead (same thing the stock KERNAL GETIN path does).
|
||||
;
|
||||
_cgetc:
|
||||
lda KEY_COUNT
|
||||
beq _cgetc ; wait until a character is available
|
||||
sei ; IRQ must not touch the buffer while we shift
|
||||
lda KEY_BUF ; first character (to be returned)
|
||||
pha
|
||||
ldx #$00
|
||||
L: lda KEY_BUF+1,x ; shift remaining characters down
|
||||
sta KEY_BUF,x
|
||||
inx
|
||||
cpx #$09 ; buffer holds 10 characters
|
||||
bne L
|
||||
dec KEY_COUNT
|
||||
cli
|
||||
pla
|
||||
ldx #$00 ; cc65 char return: char in A, high byte in X
|
||||
rts
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; PLOT - set/read cursor position (replaces kplot.o)
|
||||
;
|
||||
; cc65's kplot.o calls the original ROM PLOT ($FFF0) and UPDCRAMPTR ($EA24)
|
||||
; directly. In Open ROMs, that path runs into unimplemented code ($EA24 is a
|
||||
; KIL instruction), and the previous workaround (patching $EA24 to RTS in the
|
||||
; BIOS) left CRAM_PTR stale, breaking text colors. This replacement computes
|
||||
; SCREEN_PTR/CRAM_PTR directly - no KERNAL calls at all.
|
||||
;
|
||||
; Entry: C=0: set position (X = row, Y = column), like the KERNAL routine.
|
||||
; C=1: read position (returns X = row, Y = column, C = 0).
|
||||
;
|
||||
ZP_ROW := $FB ; temp: 16-bit offset (row*40 + col)
|
||||
ZP_ROWHI := $FC
|
||||
ZP_ROW8 := $FD ; temp: row*8
|
||||
ZP_ROW8HI := $FE
|
||||
|
||||
.proc PLOT
|
||||
bcs @read
|
||||
|
||||
; offset = row*40 + column
|
||||
stx ZP_ROW
|
||||
lda #$00
|
||||
sta ZP_ROWHI
|
||||
asl ZP_ROW
|
||||
rol ZP_ROWHI ; *2
|
||||
asl ZP_ROW
|
||||
rol ZP_ROWHI ; *4
|
||||
asl ZP_ROW
|
||||
rol ZP_ROWHI ; *8
|
||||
lda ZP_ROW
|
||||
sta ZP_ROW8
|
||||
lda ZP_ROWHI
|
||||
sta ZP_ROW8HI ; ZP_ROW8/HI = row*8
|
||||
asl ZP_ROW
|
||||
rol ZP_ROWHI ; *16
|
||||
asl ZP_ROW
|
||||
rol ZP_ROWHI ; *32
|
||||
lda ZP_ROW
|
||||
clc
|
||||
adc ZP_ROW8
|
||||
sta ZP_ROW ; + row*8 = row*40
|
||||
lda ZP_ROWHI
|
||||
adc ZP_ROW8HI
|
||||
sta ZP_ROWHI
|
||||
; NOTE: no column offset here - the KERNAL PLOT convention is that
|
||||
; SCREEN_PTR/CRAM_PTR point to the START of the cursor row; the
|
||||
; column is applied by callers via indexed addressing
|
||||
; (e.g. putchar: sta (SCREEN_PTR),y with Y = CURS_X).
|
||||
; SCREEN_PTR = $0400 + row*40
|
||||
lda #<$0400
|
||||
clc
|
||||
adc ZP_ROW
|
||||
sta SCREEN_PTR
|
||||
lda #>$0400
|
||||
adc ZP_ROWHI
|
||||
sta SCREEN_PTR+1
|
||||
; CRAM_PTR = $D800 + offset
|
||||
lda #<$D800
|
||||
clc
|
||||
adc ZP_ROW
|
||||
sta CRAM_PTR
|
||||
lda #>$D800
|
||||
adc ZP_ROWHI
|
||||
sta CRAM_PTR+1
|
||||
rts
|
||||
|
||||
@read: ldx CURS_Y
|
||||
ldy CURS_X
|
||||
clc
|
||||
rts
|
||||
.endproc
|
||||
@@ -285,7 +285,8 @@ export var PLATFORM_PARAMS = {
|
||||
arch: '6502',
|
||||
define: ['__CBM__', '__C64__'],
|
||||
cfgfile: 'c64.cfg', // SYS 2061
|
||||
libargs: ['c64.lib'],
|
||||
libargs: ['openroms-compat.o', 'c64.lib'],
|
||||
extra_link_files: ['openroms-compat.o'],
|
||||
acmeargs: ['-f', 'cbm'],
|
||||
//extra_link_files: ['c64-cart.cfg'],
|
||||
},
|
||||
|
||||
@@ -318,7 +318,7 @@ describe('Worker', function() {
|
||||
it('should compile C64 cc65 skeleton', function(done) {
|
||||
var csource = ab2str(fs.readFileSync('presets/c64/skeleton.cc65'));
|
||||
csource = csource.replace('#include "','//');
|
||||
compile('cc65', csource, 'c64.wasm', done, 3001, 3, 0);
|
||||
compile('cc65', csource, 'c64.wasm', done, 3112, 3, 0);
|
||||
});
|
||||
it('should compile zmachine inform6 skeleton', function(done) {
|
||||
var csource = ab2str(fs.readFileSync('presets/zmachine/skeleton.inform6'));
|
||||
|
||||
Reference in new issue
Block a user