diff --git a/host/src/STARTUP.s b/host/src/STARTUP.s index 60fb38f..bff5f06 100755 --- a/host/src/STARTUP.s +++ b/host/src/STARTUP.s @@ -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 - ;; from here on NMI is disabled - JMP NMI_routine_end + ;; from here on NMI is disabled + + ;; Set up IRQ for userprog transfer timer + LDA #IRQ_routine + STA $FFFF + + JMP mainsetup NMI_routine: RTI ;; exit interrupt not acknowledged -NMI_routine_end: .endscope diff --git a/host/src/mainloop.s b/host/src/mainloop.s index 3e5cc13..ce3b532 100644 --- a/host/src/mainloop.s +++ b/host/src/mainloop.s @@ -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 $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 + 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