Mercurial > hg > index.cgi
view src/init.s @ 133:c7f2f63cbcfe
Clear spurious interrupts on warm or cold start
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 24 Jun 2024 23:47:10 -0600 |
parents | a6a53e5c04bd |
children | e49bd0493baf |
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 cstackptr ; 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 lda PIA0.DA ;* clear any spurious interrupts which should work around weird bugs lda PIA0.DB ;* in emulators lda PIA1.DA lda PIA1.DB ifdef COCO3 lda GIME.IRQ lda GIME.FIRQ endc 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