Check for userprog download on a timer rather than explicitly

This commit is contained in:
John Lorentzson 2025-07-30 16:18:54 +02:00
parent 04be194c46
commit 69d9f49b5c
2 changed files with 84 additions and 26 deletions

View file

@ -69,15 +69,19 @@
;; Disable maskeble interups (not all)
SEI
;; Disable BASIC ROM mohahaha
;; Set up bank switching.
;; Disable BASIC and KERNAL(sic) ROM, keep I/O
;; https://www.c64-wiki.com/wiki/Bank_Switching
LDA #%11111110
AND $0001
STA $0001
LDA #%11111000
AND $01
STA $01
LDA #%00000101
ORA $01
STA $01
;;Disable non maskable interupts
;;https://codebase64.org/doku.php?id=base:nmi_lock_without_kernal
;; write to $FFFA/$FFFB possible (and needed) if BASIC ROM is disabled
;; write to $FFFA/$FFFB possible (and needed) if KERNAL ROM is disabled
LDA #<NMI_routine
STA $FFFA
@ -92,8 +96,14 @@
LDA #$01
STA $DD0E ;; start Timer A -> NMI
;; from here on NMI is disabled
JMP NMI_routine_end
;; Set up IRQ for userprog transfer timer
LDA #<IRQ_routine
STA $FFFE
LDA #>IRQ_routine
STA $FFFF
JMP mainsetup
NMI_routine:
RTI ;; exit interrupt not acknowledged
NMI_routine_end:
.endscope

View file

@ -1,4 +1,5 @@
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
mainsetup:
.scope mainsetup
.ifdef EMULATOR_PREVIEW
USERPROG = $C000
@ -20,6 +21,7 @@
bne @waitstart
jsr setup_loader
jmp endsetup
pha
@trying:
@ -33,19 +35,42 @@
jsr maybe_download_userprog
beq @trying
.endif
.endscope
endsetup:
DOWNLOAD_TIMER = $FFFF
lda #$0d
sta $d020
.scope mainloop
;; Turn on CIA 1's Timer A as IRQ source Summary: Timer A counts down
;; for 0xFFFF cycles. When it finishes, an IRQ is sent to the
;; CPU. Once it's ready to receive it, the IRQ routine is called,
;; which checks if a userprog download is beginning. If it is, we
;; download and reset the unwind the stack. The transfer hardware has
;; a certain delay between the transfer command being sent and the
;; start of bits being sent. This duration must be some amount longer
;; than the timer's duration to account for variable execution time of
;; interrupt-free routines.
sei ; let's be extra sure interrupts are disabled
lda #<DOWNLOAD_TIMER
sta $dc04 ; Timer A's counter low byte
lda #>DOWNLOAD_TIMER
sta $dc05 ; Likewise for high byte
lda #%10000001 ; Send IRQ to CPU when Timer A is done
sta $dc0d
lda #%00011001 ; Start Timer A, one-shot mode, cycle counting mode
sta $dc0e
ldx #$00
stx FRAMECOUNT
inx
sta FIRSTTIME
.endscope
ml:
.proc mainloop
USERPROG = $C000
RASTER = $D012
@ -54,21 +79,9 @@ ml:
ora $01
sta $01
.ifndef EMULATOR_PREVIEW
jsr maybe_download_userprog
beq @nochange
ldx #$00
stx FRAMECOUNT
inx
sta FIRSTTIME
@nochange:
.endif
cli
jsr USERPROG
;; Bank out character ROM, I/O in
lda #%00000100
ora $01
sta $01
@framewait:
ldy RASTER
cpy #$66
@ -76,8 +89,8 @@ ml:
inc FRAMECOUNT
lda #$00
sta FIRSTTIME
jmp ml
.endscope
jmp mainloop
.endproc
.proc time ; user-procedure
lda FRAMECOUNT
@ -101,6 +114,41 @@ ml:
rts
.endproc
.proc reset_userprog
ldx #$00
stx FRAMECOUNT
inx
sta FIRSTTIME
.endproc
FRAMECOUNT: .byte 0
FIRSTTIME: .byte 1
IRQ_routine:
lda $dc0d ; Check CIA 1's status
beq @somethingelse
jsr maybe_download_userprog
beq @done
jsr reset_userprog
;; Reconstruct the stack to exit to toplevel
ldx #$00
txs
lda #<mainloop
pha
lda #>mainloop
pha
txa
pha
lda #%00011001 ; Start Timer A, one-shot mode, cycle counting
sta $dc0e
rti
@somethingelse:
;; TODO: Ack potential VIC-II IRQ
@done:
lda #%00011001 ; Start Timer A, one-shot mode, cycle counting
sta $dc0e
rti