view src/init.s @ 73:2d52cd154ed1

Split some code into separate files for easier management Because the source for lwbasic is so large, split it into several different files to make it easier to navigate and modify. This is part one of the split.
author William Astle <lost@l-w.ca>
date Sun, 06 Aug 2023 00:12:29 -0600
parents
children a6a53e5c04bd
line wrap: on
line source

                *pragmapush list
                *pragma list
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
                endc
                ifne (textscreen)&0x400
                sta SAM.F1SET
                endc
                ifne (textscreen)&0x800
                sta SAM.F2SET
                endc
                ifne (textscreen)&0x1000
                sta SAM.F3SET
                endc
                ifne (textscreen)&0x2000
                sta SAM.F4SET
                endc
                ifne (textscreen)&0x4000
                sta SAM.F5SET
                endc
                ifne (textscreen)&0x8000
                sta SAM.F6SET
                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
                lda #0x12                       ; activate ROM warm start handler
                sta warmstart
                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_COCO|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
                fdb 0xfff                       ; set timer to max value
                fdb 0                           ; *reserved placeholder*
                fcb 0,0,0,0                     ; SG4 screen settings with black border
                fcb 0x0f,0xe0,0x00,0x00         ; (puts screen in bottom 64K of memory)
                fcb 0x38,0x39,0x3a,0x3b         ; MMU task 0 (bottom of top 64K of RAM)
                fcb 0x3c,0x3d,0x3e,0x3f         ; (ROM shadow must be in 3c...3f)
                fcb 0x38,0x39,0x3a,0x3b         ; 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       ldx #dpstart                    ; point to start of direct page
                ldd #0                          ; set up for blanking
coldstart0      std ,x++                        ; blank a couple of bytes
                cmpx #textscreen                ; end of low memory?
                blo coldstart0                  ; brif not
                ifndef COCO3
; This is the memory size detection sequence. This runs through memory starting at the bottom of memory
; and stops when it reaches something that can't be modified successfully. This is basically the same
; algorithm used by the stock ROM. It takes less space than doing a more pointed set of probes. The end
; result will be X pointing to the byte one below the top of RAM. This is intentional to ensure there
; is one writeable byte at the top of string space. Note that X will point to the byte after the end
; of the text screen when we get here.
                ldx #heapstart                  ; point to start of heap
coldstart1      lda 2,x                         ; get original value at test location
                coma                            ; invert all bits
                sta 2,x                         ; write it to the memory location
                cmpa 2,x                        ; did it take?
                bne coldstart2                  ; brif not
                com 2,x                         ; restore memory byte
                leax 1,x                        ; move pointer forward
                bra coldstart1                  ; go check next byte
                else
; For the Coco3, we do not need to concern ourselves about where the top actual memory is so we don't
; bother doing a memory scan in the default 64K memory map. Because we always run from RAM, we can actually
; set the top of memory to the actual top of the 32K space without having to ensure there is an extra byte
; available above the string space.
                ldx #ROMSTART-1                 ; point to top of memory
                endc
coldstart2      stx memtop                      ; save absolute top of memory
                stx memsize                     ; save top of unreserved memory
                stx stringtab                   ; mark string space as empty
                leax -200,x                     ; allocate 200 bytes of string space
                stx freetop                     ; save top of free memory
                clr ,-x                         ; make a hole for the "end of call stack" flag
                stx stackptr                    ; save the new call stack pointer
                leas ,x                         ; put the actual stack below the above
                ldx #heapstart                  ; point to start of free memory
                clr ,x+                         ; put a NUL before the start of the program
                stx progtext                    ; put the start of the program there
                clr ,x+                         ; put a NULL pointer to mark end of program
                clr ,x+
                stx vartab                      ; put start of integer variables at end of program
                stx objecttab                   ; also put the start of large objects there
                stx freestart                   ; mark the start of free memory
                lda #keyb_caps                  ; enable caps lock but disable all other shift states
                sta keyb_flags
                ldx #warmstart                  ; set up warm start handler
                stx RSTVEC
                lda #0x55                       ; activate warm start handler
                sta RSTFLG
                ldd #0x7e3b                     ; opcodes for JMP extended and RTI
                ldx #irqhandler                 ; enable IRQ handler with a JMP at the vector
                sta IRQVEC
                stx IRQVEC+1
                sta FRQVEC                      ; initialize FIRQ handler with JMP
                ldx #firqhandler
                stx FRQVEC+1
                stb NMIVEC                      ; initialize NMI to RTI
                stb SW3VEC                      ; initialize SWI3 to RTI
                stb SW2VEC                      ; initialize SWI2 to RTI
                stb SWIVEC                      ; initialize SWI to RTI
                ldx #greeting                   ; display greeting
                jsr console_outstr
                bra warmstartb                  ; finish up initialization
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Warm start handling
                ifdef COCO3
warmstart       fcb 0xff                        ; set to 0xff to force ROM/RAM copy on reset
                else
warmstart       nop                             ; flag warm start routine as valid
                endc
                jsr console_clear               ; clear screen
                clr filenum                     ; reset I/O channel to the screen
warmstartb      jsr keyb_reset                  ; reset the keyboard
                lda #0x35                       ; enable VSYNC interrupt in PIA
                sta PIA0.CB
                andcc #0xaf                     ; enable interrupts at the cpu
                jmp immediate                   ; go start immediate mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; System startup message
; (start with form feed to clear screen; saves 2 bytes over 'jsr console_clear' in cold start)
greeting        fcc '\fLWBASIC VERSION 2022.0\r\n'
                fcc 'COPYRIGHT (C) 2022 BY LOST\r\n'
                fcc 'WIZARD ENTERPRISES INC.\r\n'
                fcn '\n'
                *pragmapop list