view src/lwbasic.s @ 5:80c18925436d

More Coco3 specific initialization and interrupt vectors Set up interrupt vectors, both Coco3 and Coco1/2 vectors and also implement ROM/RAM copy for the Coco3. The warm start detection is also compatible with the stock ROM.
author William Astle <lost@l-w.ca>
date Fri, 04 Nov 2022 00:29:38 -0600
parents 2b6e6b827bd7
children 80b9b4503bb4
line wrap: on
line source

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; LWBasic Version 0.1
; Copyright © 2022 Lost Wizard Enterprises Incorporated
;
; This is LWBasic, a replacement Basic ROM system for the TRS-80 Color Computer which
; is most definitely not binary compatible with the stock ROMs.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                *pragmapush list
                *pragma nolist
                *pragma noexpandcond
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                
; Utility macros
;
; skip next byte; flags preserved
skip1           macro noexpand
                fcb 0x21                        ; opcode for BRN
                endm
; skip next byte and load nonzero to A
skip1lda        macro noexpand
                fcb 0x86                        ; opcode for LDA immediate
                endm
; skip next byte and load nonzero to B
skip1ldb        macro noexpand
                fcb 0xc6                        ; opcoe for LDB immediate
                endm
; skip next 2 bytes; clobbers flags
skip2           macro noexpand
                fcb 0x8c                        ; opcode for CMPX immediate
                endm
                *pragmapop list
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Various constants
                ifdef COCO3
; GIME INIT0
GIME_COCO       equ 0x80                        ; Set for coco2 compatible mode (video display)
GIME_MMUEN      equ 0x40                        ; Set to enable MMU
GIME_IEN        equ 0x20                        ; GIME IRQ enable
GIME_FEN        equ 0x10                        ; GIME FIRQ enable
GIME_FExx       equ 0x08                        ; Enable constant RAM at 0xFExx (comes from block 0x3f)
GIME_SCS        equ 0x04                        ; Set to enable standard SCS (switches 0xFF5x)
GIME_ROME16     equ 0x00                        ; 16K internal, 16K external ROM mode
GIME_ROME32     equ 0x03                        ; 32K external ROM
GIME_ROMI32     equ 0x02                        ; 32K internal ROM
; GIME INIT1
GIME_TMRFAT     equ 0x20                        ; TIMER ticks approx every 279.365 ns
GIME_TMRSLOW    equ 0x00                        ; TIMER ticks approx every 63.695 µs
GIME_TASK0      equ 0x00                        ; MMU task 0
GIME_TASK1      equ 0x01                        ; MMU task 1
; GIME interrupt enable/status bits
GIME_ITIMER     equ 0x20                        ; TIMER interrupt (timer reaches 0)
GIME_IHBORD     equ 0x10                        ; HSYNC interrupt (falling edge)
GIME_IVBORD     equ 0x08                        ; VSYNC interrupt (falling edge)
GIME_ISERIAL    equ 0x04                        ; Falling edge of signal on pin 4 of serial port
GIME_IKEYBOARD  equ 0x02                        ; Interrupt if a 0 bit appears on bits 6-0 of PIA0.DA
GIME_ICART      equ 0x01                        ; Interrupt on falling edge of pin 8 of cartridge port
; GIME VMODE
GIME_BP         equ 0x80                        ; enable bit plane mode
GIME_BPI        equ 0x20                        ; colour burst phase inversion (composite output only)
GIME_MONO       equ 0x10                        ; disable colour burst (composite output only)
GIME_H50        equ 0x08                        ; set to 50Hz operation
GIME_LPR1       equ 0x00                        ; one line per row
GIME_LPR2       equ 0x02                        ; two lines per row (also works on graphics)
GIME_LPR8       equ 0x03                        ; 8 lines per row
GIME_LPR9       equ 0x04                        ; 9 lines per row
GIME_LPR10      equ 0x05                        ; 10 lines per row
GIME_LPR11      equ 0x06                        ; 11 lines per row
GIME_LPRINF     equ 0x07                        ; "infinite" lines per row
; GIME VRES
GIME_LPF192     equ 0x00                        ; 192 lines on screen
GIME_LPF200     equ 0x40                        ; 200 lines on screen (actually 199 due to hardware bug)
GIME_LPF225     equ 0x60                        ; 225 lines on screen
GIME_BPR16      equ 0x00                        ; 16 bytes per row
GIME_BPR20      equ 0x04                        ; 20 bytes per row
GIME_BPR32      equ 0x08                        ; 32 bytes per row
GIME_BPR40      equ 0x0c                        ; 40 bytes per row
GIME_BPR64      equ 0x10                        ; 64 bytes per row
GIME_BPR80      equ 0x14                        ; 80 bytes per row
GIME_BPR128     equ 0x18                        ; 128 bytes per row
GIME_BPR160     equ 0x1c                        ; 160 bytes per row
GIME_TXT32      equ 0x00                        ; 32 characters per row
GIME_TXT40      equ 0x04                        ; 40 characters per row
GIME_TXT64      equ 0x10                        ; 64 characters per row
GIME_TXT80      equ 0x14                        ; 80 characters per row
GIME_BPP1       equ 0x00                        ; 1 bit per pixel
GIME_BPP2       equ 0x01                        ; 2 bits per pixel
GIME_BPP4       equ 0x02                        ; 4 bits per pixel
GIME_TXTATTR    equ 0x01                        ; text attributes enabled
                endc
                ifdef COCO3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Stuff on the fixed memory page
                org 0xfe00
                rmb 0xed                        ; unused
INT.FLAG        rmb 1                           ; validity flag
INT.SWI3        rmb 3                           ; SWI3 bounce vector
INT.SWI2        rmb 3                           ; SWI2 bounce vector
INT.FIRQ        rmb 3                           ; FIRQ bounce vector
INT.IRQ         rmb 3                           ; IRQ bounce vector
INT.SWI         rmb 3                           ; SWI bounce vector
INT.NMI         rmb 3                           ; NMI bounce vector
                endc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Hardware definitions for the I/O page
                org 0xff00
PIA0            equ *                           ; Keyboard PIA
PIA0.DA         rmb 1                           ; PIA0 data/direction A
PIA0.CA         rmb 1                           ; PIA0 control A
PIA0.DB         rmb 1                           ; PIA0 data/direction B
PIA0.CB         rmb 1                           ; PIA0 control B
                rmb 28                          ; mirror images of PIA0
PIA1            equ *                           ; DA/misc stuff
PIA1.DA         rmb 1                           ; PIA1 data/direction A
PIA1.CA         rmb 1                           ; PIA1 control A
PIA1.DB         rmb 1                           ; PIA1 data/direction B
PIA1.CB         rmb 1                           ; PIA1 control B
                rmb 28                          ; mirror images of PIA1
                rmb 16                          ; SCS/Disk controller
                rmb 16                          ; second half of SCS area
                rmb 32                          ; miscelaneous hardware
                ifdef COCO3
                rmb 16                          ; *reserved* (unused but the GIME drives them)
GIME.INIT0      rmb 1                           ; basic GIME system config
GIME.INIT1      rmb 1                           ; MMU task and timer rate
GIME.IRQ        rmb 1                           ; GIME IRQ enable/status register
GIME.FIRQ       rmb 1                           ; GIME FIRQ enable/status register
GIME.TIMER      rmb 2                           ; GIME programmable timer
                rmb 2                           ; *reserved*
GIME.VMODE      rmb 1                           ; GIME video mode setting
GIME.VRES       rmb 1                           ; GIME video resolution setting
                rmb 1                           ; *reserved* (used for MMU expansion on some memory boards)
GIME.BORDER     rmb 1                           ; GIME border colour
GIME.VSCROLL    rmb 1                           ; vertical scroll offset register/VDG screen mode variation
GIME.VOFFSET    rmb 2                           ; address of video memory (8 byte increments)
GIME.HOFFSET    rmb 1                           ; horizontal scroll offset
GIME.MMU        equ *                           ; MMU registers (two tasks)
GIME.MMU0       rmb 8                           ; MMU task 0
GIME.MMU1       rmb 8                           ; MMU task 1
GIME.PALETTE    rmb 16                          ; Palette registers
                else
                rmb 64                          ; unused on Coco 1/2 (GIME on Coco 3)
                endc
SAMREG          equ *                           ; the SAM configuration register
SAM.V0CLR       rmb 1                           ; SAM video mode bits
SAM.V0SET       rmb 1
SAM.V1CLR       rmb 1
SAM.V1SET       rmb 1
SAM.V2CLR       rmb 1
SAM.V2SET       rmb 1
SAM.F0CLR       rmb 1                           ; SAM screen address bits
SAM.F0SET       rmb 1
SAM.F1CLR       rmb 1
SAM.F1SET       rmb 1
SAM.F2CLR       rmb 1
SAM.F2SET       rmb 1
SAM.F3CLR       rmb 1
SAM.F3SET       rmb 1
SAM.F4CLR       rmb 1
SAM.F4SET       rmb 1
SAM.F5CLR       rmb 1
SAM.F5SET       rmb 1
SAM.F6CLR       rmb 1
SAM.F6SET       rmb 1
SAM.P1CLR       rmb 1                           ; SAM "page 1" selection (or extra memory type flag)
SAM.P1SET       rmb 1
SAM.R0CLR       rmb 1                           ; SAM R0 bit (address dependent speedup, not used on Coco3)
SAM.R0SET       rmb 1
SAM.R1CLR       rmb 1                           ; SAM R1 bit (full speedup/coco 3 speedup)
SAM.R1SET       rmb 1
SAM.M0CLR       rmb 1                           ; SAM M0/M1 bits (memory type, not used on Coco3)
SAM.M0SET       rmb 1
SAM.M1CLR       rmb 1
SAM.M1SET       rmb 1
SAM.TYCLR       rmb 1                           ; force ROM mode (map type 0)
SAM.TYSET       rmb 1                           ; set RAM mode (map type 1)
                rmb 18                          ; *MPU reserved*
CPU.SWI3        rmb 2                           ; CPU SWI3 vector
CPU.SWI2        rmb 2                           ; CPU SWI2 vector
CPU.FIRQ        rmb 2                           ; CPU FIRQ vector
CPU.IRQ         rmb 2                           ; CPU IRQ vector
CPU.SWI         rmb 2                           ; CPU SWI vector
CPU.NMI         rmb 2                           ; CPU NMI vector
CPU.RESET       rmb 2                           ; CPU RESET/startup vector
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Start of memory which has the direct page and other data.
                org 0
                rmb 0x71-*                      ; align RSTFLG/RSTVEC for stock ROM compatibility
RSTFLG          rmb 1                           ; 0x55 if RSTVEC is valid
RSTVEC          rmb 2                           ; points to warm start routine (must start with NOP)
                rmb 0x100-*                     ; make sure the stuff that isn't direct page is outside of it
SW3VEC          rmb 3                           ; SWI3 vector (for compatibility)
SW2VEC          rmb 3                           ; SWI2 vector (for compatibility)
SWIVEC          rmb 3                           ; SWI vector (for compatibility)
NMIVEC          rmb 3                           ; NMI vector (for compatibility)
IRQVEC          rmb 3                           ; IRQ vector (for compatibility)
FRQVEC          rmb 3                           ; FIRQ vector (for compatibility)
                rmb 0xee                        ; unused
textscreen      rmb 0x200                       ; the actual text screen (must be on 512 byte alignment)
                org 0x8000                      ; the hardware puts the ROMs here; it's not negotiable
START           orcc #0x50                      ; make sure interrupts are disabled if we come here in an unusual way
                ifdef COCO3
                ldu #gime_inite                 ; point to end of GIME initializer
                ldx #GIME.INIT0+(gime_inite-gime_init) ; point to end of GIME registers
                ldb #gime_inite-gime_init       ; number of bytes to transfer
initc0          lda ,-u                         ; copy byte to GIME (count down so we init MMU before turning it on)
                sta ,-x
                decb                            ; done?
                bne initc0                      ; brif not
                endc
                ldd #0xff34                     ; initizer for below
                tfr a,dp                        ; set DP to I/O page
                setdp 0xff                      ; tell assembler about DP value
                clr PIA0.CA                     ; set PIA0 A to direction mode
                clr PIA0.CB                     ; set PIA0 B to direction mode
                clr PIA0.DA                     ; set PIA0 A to all inputs (comparator, keyboard rows)
                sta PIA0.DB                     ; set PIA0 B to all outputs (keyboard columns)
                stb PIA0.CA                     ; set PIA0 A to data mode, interrupt disabled, MUX to source 0
                stb PIA0.CB                     ; set PIA0 B to data mode, interrupt disabled, MUX to source 0
                clr PIA1.CA                     ; set PIA1 A to direction mode
                clr PIA1.CB                     ; set PIA1 B to direction mode
                deca                            ; set PIA1 A bits 7-1 output (DAC, RS232), 0 input (cassette)
                sta PIA1.DA
                lda #0xf8                       ;* set PIA1 B bits 7-3 output (VDG stuff), 2-0 input (single bit sound,
                sta PIA1.DB                     ;* RS232 input, ram size input)
                stb PIA1.CA                     ; set PIA1 A to data mode, interrupt disabled, cassette motor off
                stb PIA1.CB                     ; set PIA1 B to data mode, interrupt disabled, sound off
                lda #2                          ; set RS232 output to "marking" (stop bit)
                sta PIA1.DA
                lda #16                         ; clear 16 SAM register bits
                ldu #SAMREG                     ; point to SAM register bits
init0           sta ,u++                        ; clear SAM bit
                deca                            ; done all?
                bne init0                       ; brif not
; set the SAM to point to the text screen, which the code will handle at any
; arbitrary 512 byte aligned address in memory
                ifne (textscreen)&0x200
                sta (SAM.F0SET-SAMREG)-16,u
                endc
                ifne (textscreen)&0x400
                sta (SAM.F1SET-SAMREG)-16,u
                endc
                ifne (textscreen)&0x800
                sta (SAM.F2SET-SAMREG)-16,u
                endc
                ifne (textscreen)&0x1000
                sta (SAM.F3SET-SAMREG)-16,u
                endc
                ifne (textscreen)&0x2000
                sta (SAM.F4SET-SAMREG)-16,u
                endc
                ifne (textscreen)&0x4000
                sta (SAM.F5SET-SAMREG)-16,u
                endc
                ifne (textscreen)&0x8000
                sta (SAM.F6SET-SAMREG)-16,u
                endc
                ifdef COCO2B
; The following SAM configuration sequence is different from the one in the usual
; one used by the earlier models of the Coco because the Coco2B has the '785 variant
; of the SAM instead of the '783 variant. The '785 variant supports 16Kx4 RAMs which
; are used in Coco2B systems. Hence why there is a different version of this ROM
; just for the Coco2B.
                clr PIA0.DB                     ; strobe RAM size low
                ldb #4                          ; is input low?
                bitb PIA1.DB
                beq init1                       ; brif not
                sta SAM.M0SET                   ; program SAM for 16Kx4 RAMs
                sta SAM.P1SET
                skip2
init1           sta SAM.M1SET                   ; program SAM for 64Kx1 RAMs
                else
                ifndef COCO3
; Detect the installed memory size so the SAM ('783 variant) can be correctly
; programmed for the installed memory. Note that this sequence is replaced with
; a different one for the Coco2B which has the '785 variant of the SAM.
                ldb #0xff                       ; strobe RAM size high
                stb PIA0.DB
                ldb #4                          ; mask for ram size check
                bitb PIA1.DB                    ; is the bit set on ram size input?
                beq init2                       ; brif not - 4Kx1 RAMs
                sta PIA0.DB                     ; clear RAM size output to see what happens (A is 0 from above)
                bitb PIA1.DB                    ; is it set now?
                beq init1                       ; brif not - 64Kx1 RAMs
                leau -2,u                       ; adjust pointer so we set the other RAM size bit for the SAM (16Kx1)
init1           sta -3,u                        ; set M0 (16Kx1) or M1 (64Kx1)
                endc
                endc
init2           tfr a,dp                        ; set DP to bottom of memory (A is 0 from above)
                setdp 0                         ; tell assembler about it
                lds #textscreen                 ; put the stack just below the text screen
                ifdef COCO3
; Check if we need to do a ROM/RAM copy, which will happen if the interrupt vectors are
; not flagged valid OR the reset vector isn't valid
                ldb INT.FLAG                    ; are the bounce vectors valid?
                cmpb #0x55
                bne initc4                      ; brif not - do ROM/RAM copy
                ldb RSTFLG                      ; is reset vector valid?
                bne initc2                      ; brif not - check secondary location
                ldx RSTVEC                      ; get reset vector
                ldb ,x                          ; is it valid?\
                cmpb #0x12
                bne initc2                      ; brif not
initc1          jmp ,x                          ; transfer control to warm start routine
initc2          clr GIME.MMU0                   ; check again with block 0 in the direct page
                ldb RSTFLG                      ; get new RSTFLG
                cmpb #0x55                      ; valid?
                bne initc3                      ; brif not
                ldx RSTVEC                      ; get new RSTVEC
                ldb ,x                          ; is it valid?
                cmpb #0x12
                beq initc1                      ; brif so - transfer control
initc3          ldb #0x38                       ; restore MMU
                stb GIME.MMU0
initc4          ldx #initc6                     ; point to helper
                ldu #textscreen                 ; point to text screen
                ldb #initc7-initc6              ; bytes to copy
initc5          lda ,x+                         ; copy byte
                sta ,u+
                decb                            ; done?
                bne initc5                      ; brif not
                ldu #0x8000                     ; point to start of ROM
                jmp textscreen                  ; transfer control to helper in RAM
initc6          sta SAM.TYCLR                   ; drop to ROM mode
                pulu d,x,y,s                    ; grab 8 bytes
                sta SAM.TYSET                   ; go to RAM mode
                pshu d,x,y,s                    ; stick the bytes in RAM
                leau 8,u                        ; move to next 8 bytes
                cmpu #0xfe00                    ; end of stuff to copy?
                blo initc6                      ; brif not
                jmp initc7                      ; go back to mainline
initc7          lds #textscreen                 ; reset stack to somewhere safe
                ldx #INT.FLAG                   ; point to bounce vector destination
                ldu #int_init                   ; point to initializer for bounce vectors
                ldb #int_inite-int_init         ; number of bytes to copy
initc8          lda ,u+                         ; copy byte
                sta ,x+
                decb                            ; done?
                bne initc8                      ; brif not
; now recheck for warm start in case ROM/RAM copy made things valid
                endc
                ldb RSTFLG                      ; is the reset vector valid?
                cmpb #0x55
                bne coldstart                   ; brif not - do cold start
                ldx RSTVEC                      ; get warm start routine pointer
                ldb ,x                          ; does it start with NOP?
                cmpb #0x12
                bne coldstart                   ; brif not - do cold start
                jmp ,x                          ; transfer control to warm start routine
                ifdef COCO3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GIME register initializer
gime_init       fcb GIME_MMUEN|GIME_FExx|GIME_SCS|GIME_ROMI32 ; enable MMU, SCS, constant page, internal ROM
                fcb GIME_TASK0                  ; use MMU task 0
                fcb 0                           ; do not enable IRQ sources
                fcb 0                           ; do not enable FIRQ sources
                fcb 0xfff                       ; set timer to max value
                fdb 0                           ; *reserved placeholder*
                fcb 0,0,0,0                     ; SG4 screen settings with black border
                fcb 0x0f,0x00,0x00,0x00         ; (puts screen in bottom 64K of memory)
                fcb 0x00,0x01,0x02,0x03         ; MMU task 0 (non-ROM area at bottom of RAM)
                fcb 0x3c,0x3d,0x3e,0x3f         ; (ROM shadow must be in 3c...3f)
                fcb 0x00,0x01,0x02,0x03         ; MMU task 1 (copy of task 0)
                fcb 0x3c,0x3d,0x3e,0x3f
                fcb 18,54,9,36,63,27,45,38      ; palette values (RGB)
                fcb 0,18,0,63,0,18,0,38
gime_inite      equ *
int_init        fcb 0x55                        ; vectors valid flag
                jmp SW3VEC                      ; bounce to stock ROM compatibility vector
                jmp SW2VEC                      ; bounce to stock ROM compatibility vector
                jmp FRQVEC                      ; bounce to stock ROM compatibility vector
                jmp IRQVEC                      ; bounce to stock ROM compatibility vector
                jmp SWIVEC                      ; bounce to stock ROM compatibility vector
                jmp NMIVEC                      ; bounce to stock ROM compatibility vector
int_inite       equ *
                endc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cold start handling
coldstart       
                ifndef COCO3
; Need to ensure the vectors are at 0xbff2
                zmb 0xbff2-*                    ; pad ROM up to the vector point
                fdb SW3VEC                      ; SWI3 vector
                fdb SW2VEC                      ; SWI2 vector
                fdb FRQVEC                      ; FIRQ vector
                fdb IRQVEC                      ; IRQ vector
                fdb SWIVEC                      ; SWI vector
                fdb NMIVEC                      ; NMI vector
                fdb START                       ; RESET vector (ROM entry point)
                endc
                ifdef COCO3
                zmb 0xfff2-*                    ; pad ROM to bottom of vectors
                fdb INT.SWI3                    ; SWI3 vector
                fdb INT.SWI2                    ; SWI2 vector
                fdb INT.FIRQ                    ; FIRQ vector
                fdb INT.IRQ                     ; IRQ vector
                fdb INT.SWI                     ; SWI vector
                fdb INT.NMI                     ; NMI vector
                fdb START                       ; RESET vector (ROM entry point)
                else
                zmb 0x10000-*                   ; pad ROM to full size
                endc