boot.s   boot.s 
;;; ;;;
;;; A Fuzix booter for the CoCo3 ;;; A Fuzix booter for the CoCo2/3
;;;
;;; 2015-06-17: Brett Gordon: Original work
;;; 2016-12-10: Michael Furman: Hack it up for Coco2
;;; ;;;
;;; This bootloader works from a DECB-like evironment, It loads ;;; This bootloader works from a DECB-like evironment, It loads
;;; FUZIX.BIN from a DECB disk and plops it in memory, starting ;;; FUZIX.BIN from a DECB disk and plops it in memory, starting
;;; at physical address 0x0000. ;;; at physical address 0x0000.
IFDEF COCO2
org $1000 ; where am I loaded.
MYSTART EQU . ; first address this program uses
STKSTRT equ $18FF ; put the stack here
MYEND equ STKSTRT+1 ; last address this program uses
LOADLOC equ $8000 ; load the program in high ram
COPYEND equ $FF00 ; end of high ram
SDCBANK equ 1 ; CocoSDC Bank
RAMROM equ $FFDE ; poke to switch to RAM/ROM
ALLRAM equ $FFDF ; poke to switch to all RAM
ROMSTRT equ $C000 ; Address where FUZIX ROM starts
ELSE
org $7a00 ; where am I loaded. org $7a00 ; where am I loaded.
ENDC
frame .dw 0 ; on entry frame pointer frame .dw 0 ; on entry frame pointer
npage .db 0 ; next page no. npage .db 0 ; next page no.
pos .dw 0 ; buffer pos in memory pos .dw 0 ; buffer pos in memory
tickp .dw $400+(32*15) ; ticker next position tickp .dw $400+(32*15) ; ticker next position
tickb .db 0 ; tickb .db 0 ;
size .dw 0 ; no of grans size .dw 0 ; no of grans
secs .dw 0 ; init value of of sectors for each screen block secs .dw 0 ; init value of of sectors for each screen block
scount .dw 0 ; sector counter scount .dw 0 ; sector counter
nampre fcn /"FUZIX.BIN/ ; " image to load nampre fcn /"FUZIX.BIN/ ; " image to load
rmb 6 ; pad for max filename rmb 6 ; pad for max filename
wbuf rmb 32 ; word buffer for cmdline parsing wbuf rmb 32 ; word buffer for cmdline parsing
wptr .dw $88 ; static data for word routine wptr .dw $88 ; static data for word routine
bootstr fcn "BOOT=" bootstr fcn "BOOT="
fnf .db 13 fnf .db 13
fcc "KERNEL FILE NOT FOUND" fcc "KERNEL FILE NOT FOUND"
.db 13 .db 13
.db 0 .db 0
; fuzixfs filename block for SDC
fuzixfs
.ascii "M:FUZIXFS.DSK"
ZMB 256-(.-fuzixfs)
;;; CocoSDC
SDCLTCH equ $FF40
SDCCREG equ $FF48
SDCSTAT equ $FF48
SDCPRM1 equ $FF49
SDCPRM2 equ $FF4A
SDCPRM3 equ $FF4B
SDCDATA equ SDCPRM2
SDCDATB equ SDCPRM3
; Basic Variables
CHARAD equ $88
; Color Basic Routines
PUTCHR equ $A282
PUTSTR equ $B99C
FCLOSE equ $A42D
; Disk Basic 1.1 Routines
DBNAMF equ $C935
SRCHDIR equ $C68C
GRANCNT equ $CD1E
OPENDF equ $C48D
;; And the Kick-off ;; And the Kick-off
start start
sts frame sts frame
IFDEF COCO2
;; move the stack because fuzix may load on top of it
;; XXX: safety or will decb barf up on this??
lds #STKSTRT
ENDC
lda #13 lda #13
jsr 0xa282 jsr PUTCHR
ldd #$400+(32*14) ldd #$400+(32*14)
std $88 std CHARAD
lda #'F ; print F lda #'F ; print F
jsr 0xa282 ; jsr PUTCHR ;
IFNDEF COCO2
;; Move to task one ;; Move to task one
ldx #$ffa0 ldx #$ffa0
ldu #$ffa8 ldu #$ffa8
ldd ,x++ ; copy mmu regs ldd ,x++ ; copy mmu regs
std ,u++ std ,u++
ldd ,x++ ldd ,x++
std ,u++ std ,u++
ldd ,x++ ldd ,x++
std ,u++ std ,u++
ldd ,x++ ldd ,x++
std ,u++ std ,u++
ldb #1 ldb #1
stb $ff91 ; set mmu to task 1 stb $ff91 ; set mmu to task 1
ENDC
;; XXX: not sure what do do here for Coco2?
IFNDEF COCO2
;; move and process command line ;; move and process command line
jsr cpcmd jsr cpcmd
jsr bootfile jsr bootfile
ENDC
;; open kernel image file ;; open kernel image file
ldb #'I ; input mode ldb #'I ; input mode
jsr open jsr open
lbcs abort lbcs abort
lda #'U ; print "U" lda #'U ; print "U"
jsr $a282 jsr PUTCHR
;; calculate sectors for each screen block ;; calculate sectors for each screen block
ldd size ldd size
lsra lsra
rorb rorb
lsra lsra
rorb rorb
lsra lsra
rorb rorb
lsra lsra
rorb rorb
skipping to change at line 86 skipping to change at line 139
pshs b ; save on stack pshs b ; save on stack
ldb #1 ldb #1
stb $6f ; switch in/out routine to disk file #1 stb $6f ; switch in/out routine to disk file #1
c@ jsr $a176 ; get a byte in A c@ jsr $a176 ; get a byte in A
cmpa #$ff ; compare A to ff cmpa #$ff ; compare A to ff
beq post ; jump to post able handling beq post ; jump to post able handling
;; preamble ;; preamble
jsr getw ; D = length address jsr getw ; D = length address
tfr d,y ; U = length tfr d,y ; U = length
jsr getw ; D = load address jsr getw ; D = load address
jsr setload ; set load address IFDEF COCO2
; skip the rom bytes, read entire section but don't copy to ram
cmpd #ROMSTRT
blo cc@
s@ jsr $a176 ; A = byte
jsr tick
leay -1,y ; decrement U
bne s@ ; loop
bra c@ ; try next byte in stream
ENDC
cc@ jsr setload ; set load address
d@ jsr $a176 ; A = byte d@ jsr $a176 ; A = byte
jsr tick jsr tick
jsr putb ; put into kernel memory jsr putb ; put into kernel memory
leay -1,y ; decrement U leay -1,y ; decrement U
bne d@ ; loop bne d@ ; loop
bra c@ ; try next byte in stream bra c@ ; try next byte in stream
;; postable ;; postable
post jsr getw ; get zero's post jsr getw ; get zero's
cmpd #0 ; test D cmpd #0 ; test D
lbne abort ; abort if not zero lbne abort ; abort if not zero
jsr getw ; get exec address jsr getw ; get exec address
pshs d ; save on stack pshs d ; save on stack
jsr close ; close DECB file jsr close ; close DECB file
;; report load ;; report load
clr $6f ; set stream to console clr $6f ; set stream to console
lda #'L lda #'L
jsr $A282 jsr PUTCHR
IFNDEF COCO2
ldd #0 ; Address = 0 ldd #0 ; Address = 0
jsr setload jsr setload
ldy #bounce_end-bounce ldy #bounce_end-bounce
ldx #bounce ldx #bounce
e@ lda ,x+ e@ lda ,x+
jsr putb jsr putb
leay -1,y leay -1,y
bne e@ bne e@
lda ,s+ ; get jmp address high byte lda ,s+ ; get jmp address high byte
jsr putb ; put at end of bounce routine jsr putb ; put at end of bounce routine
lda ,s+ lda ,s+
jsr putb ; put at end of bounce routine jsr putb ; put at end of bounce routine
lda #'O lda #'O
jsr $a282 ; report load jsr PUTCHR ; report load
;; map in kernel block 0 ENDC
orcc #$50 ; turn off interrupts orcc #$50 ; turn off interrupts
IFDEF COCO2
; basic is toast after moving, save basic cursor pos
ldx CHARAD
stx tickp
jsr mover
lda #'O
jsr myputc ; report load
;; mount fuzixfs
ldy #fuzixfs
jsr mountFs
lda #'M
jsr myputc ; report mount
;; flip the sdc flash bank
lda #SDCBANK
sta $ff43
lda #'F
jsr myputc ; report flip
jmp $c000 ; jump into the kernel
; testing
;sta ALLRAM
;bra .
ELSE
;; map in kernel block 0
clr $ffa8 ; put bounce routine in memory clr $ffa8 ; put bounce routine in memory
jmp $0 ; and jump to bounce routine jmp $0 ; and jump to bounce routine
ENDC
IFDEF COCO2
;;; Move kernel data from high to low ram
;;; Skiping this code section
mover
;; enter all ram mode
sta ALLRAM
;; Turn off interrupts
orcc #(0x10|0x40)
;; save the screen
ldx #$400
ldy #$8400
cpylp@ cmpx #$600
beq done@
ldd ,x++
std ,y++
bra cpylp@
done@
;; do the copy
ldx #LOADLOC
ldy #0
mvlp@ cmpx #COPYEND
beq done@
cmpy #MYSTART
blo copy@
cmpy #MYEND
bge copy@
leax 2,x
leay 2,y
bra mvlp@
copy@
ldd ,x++
std ,y++
bra mvlp@
done@ sta RAMROM
rts
ENDC
;; Put characters on the screen after basic is toasted
myputc
ldx tickp
sta ,x+
stx tickp
rts
;;; copy cmdline down to kernel 0 ;;; copy cmdline down to kernel 0
cpcmd ;; find command line in input buffer cpcmd ;; find command line in input buffer
ldd #$88 ; set destination of cpy in kernel memory ldd #$88 ; set destination of cpy in kernel memory
jsr setload ; jsr setload ;
ldx $a6 ; X = position in program ldx $a6 ; X = position in program
a@ lda ,x+ ; get a byte a@ lda ,x+ ; get a byte
beq c@ ; end of line w/o remark token? beq c@ ; end of line w/o remark token?
cmpa #$83 ; is a ' token? cmpa #$83 ; is a ' token?
beq b@ beq b@
skipping to change at line 195 skipping to change at line 329
decb decb
bne b@ bne b@
;; ok we've found a "BOOT=": copy arg to filename buffer ;; ok we've found a "BOOT=": copy arg to filename buffer
ldx #nampre+1 ldx #nampre+1
c@ lda ,u+ ; get a byte c@ lda ,u+ ; get a byte
sta ,x+ ; store a byte in buffer sta ,x+ ; store a byte in buffer
bne c@ ; repeat if not zero bne c@ ; repeat if not zero
;; out of cmd to parse ;; out of cmd to parse
out@ puls d,x,u,pc out@ puls d,x,u,pc
IFNDEF COCO2
;;; This routine is copied down to kernel map 0 ;;; This routine is copied down to kernel map 0
bounce bounce
;; map in rest of kernel ;; map in rest of kernel
ldx #$ffa9 ldx #$ffa9
lda #1 lda #1
a@ sta ,x+ a@ sta ,x+
inca inca
cmpa #8 cmpa #8
bne a@ bne a@
.db $7e ; jump .db $7e ; jump
bounce_end bounce_end
ENDC
;;; Gets next word from file ;;; Gets next word from file
;;; takes: nothing ;;; takes: nothing
;;; returns: D = next word ;;; returns: D = next word
getw getw
jsr $a176 ; A = high byte jsr $a176 ; A = high byte
tfr a,b ; B = high byte tfr a,b ; B = high byte
jsr $a176 ; A = low byte jsr $a176 ; A = low byte
exg a,b ; flip D = next word exg a,b ; flip D = next word
jsr tick jsr tick
jsr tick jsr tick
rts rts
;;; Sets load address ;;; Sets load address
;;; takes: D = Address ;;; takes: D = Address
;;; returns: X = cpu mapped address ;;; returns: X = cpu mapped address
;;; mods: D ;;; mods: D
setload setload
IFDEF COCO2
addd #LOADLOC
ELSE
pshs d pshs d
;; find block number ;; find block number
lsra lsra
lsra lsra
lsra lsra
lsra lsra
lsra ; A= blk no lsra ; A= blk no
sta $ffaa ; put in mmu sta $ffaa ; put in mmu
puls d puls d
anda #$1f ; D = offset anda #$1f ; D = offset
addd #$4000 ; mmu offset addd #$4000 ; mmu offset
ENDC
std pos ; store std pos ; store
rts rts
;;; puts a byte into kernel memory, increments position ;;; puts a byte into kernel memory, increments position
;;; takes: A = byte to store ;;; takes: A = byte to store
;;; returns: nothing ;;; returns: nothing
;;; mods: ;;; mods:
putb pshs d,x putb
IFDEF COCO2
pshs x
ldx pos
orcc #(0x10|0x40)
sta ALLRAM
sta ,x+
sta RAMROM
andcc #~(0x10|0x40)
stx pos
puls x,pc
rts
ELSE
pshs d,x
a@ ldx pos a@ ldx pos
cmpx #$6000 ; too far ? cmpx #$6000 ; too far ?
beq inc@ beq inc@
sta ,x+ sta ,x+
stx pos stx pos
puls d,x,pc puls d,x,pc
inc@ ldx #$4000 ; inc pos inc@ ldx #$4000 ; inc pos
stx pos stx pos
inc $ffaa inc $ffaa
bra a@ bra a@
ENDC
;;; Abort! ;;; Abort!
abort abort
ldx #fnf-1 ldx #fnf-1
jsr $b99c jsr PUTSTR
lds frame lds frame
rts rts
;;; Open a file ;;; Open a file
;;; takes: B=ascii mode (I,O,D) ;;; takes: B=ascii mode (I,O,D)
;;; returns: C set on error ;;; returns: C set on error
open pshs b ; save mode open pshs b ; save mode
;; move local filename into BASIC's vars ;; move local filename into BASIC's vars
ldx $a6 ldx $a6
pshs x pshs x
ldx #nampre ; pointer to our local filename ldx #nampre ; pointer to our local filename
stx $a6 ; set CHARAD stx $a6 ; set CHARAD
jsr $c935 ; have BASIC set up DNAMBF for us jsr DBNAMF ; have BASIC set up DNAMBF for us
puls x puls x
stx $a6 stx $a6
;; end of string copy - get directory info ;; end of string copy - get directory info
f@ jsr $c68c ; search directory, U=ram directory image f@ jsr SRCHDIR ; search directory, U=ram directory image
tst $973 ; found? tst $973 ; found?
bne g@ ; yes - then return bne g@ ; yes - then return
;; not found ;; not found
ldb ,s ; get mode ldb ,s ; get mode
cmpb #'I ; is mode I? cmpb #'I ; is mode I?
beq err@ ; yes then error! beq err@ ; yes then error!
ldd #$00ff ; basic/ascii ldd #$00ff ; basic/ascii
bra h@ bra h@
;; get size of file in granuals ;; get size of file in granuals
g@ pshs d,x,u g@ pshs d,x,u
ldb 2,u ; B = first granuals of file ldb 2,u ; B = first granuals of file
jsr $cd1e ; get no of granuals jsr GRANCNT ; get no of granuals
andb #0xf ; B = sectors used in last granual andb #0xf ; B = sectors used in last granual
pshs b ; save on stack ( last ) pshs b ; save on stack ( last )
clr ,-s ; as 16 bit value clr ,-s ; as 16 bit value
deca ; A = whole granuals deca ; A = whole granuals
ldb #9 ldb #9
mul ; D = sectors mul ; D = sectors
addd ,s++ ; D = sectors in file addd ,s++ ; D = sectors in file
std size ; save std size ; save
puls d,x,u puls d,x,u
;; copy directory stuff ;; copy directory stuff
ldd ,u ; D = type/ascii ldd ,u ; D = type/ascii
ldb #$ff ; force ascii ldb #$ff ; force ascii
h@ std $957 h@ std $957
ldd #$100 ; record length ldd #$100 ; record length
std $976 std $976
lda ,s ; A = Mode (I,O,D) lda ,s ; A = Mode (I,O,D)
ldb #1 ; B = FCB #1 ldb #1 ; B = FCB #1
jsr $c48d ; open file jsr OPENDF ; open file
out@ clra ; clear C out@ clra ; clear C
puls b,pc ; return puls b,pc ; return
err@ coma ; set C err@ coma ; set C
puls b,pc ; return puls b,pc ; return
;;; Close file buffer ;;; Close file buffer
close close
ldb #1 ; set file number to 1 ldb #1 ; set file number to 1
stb $6f stb $6f
jsr $a42d ; close file jsr FCLOSE ; close file
clr $6f ; set dev to screen clr $6f ; set dev to screen
rts rts
;;; Tick the ticker ;;; Tick the ticker
tick tick
pshs d,x pshs d,x
inc tickb ; inc byte counter inc tickb ; inc byte counter
bne out@ ; return if not 256 bytes bne out@ ; return if not 256 bytes
;; decrement block counter ;; decrement block counter
ldd scount ldd scount
skipping to change at line 337 skipping to change at line 491
bne out@ ; leave if sector/block counter is not done bne out@ ; leave if sector/block counter is not done
;; else put new screen block ;; else put new screen block
ldd secs ldd secs
std scount std scount
ldb #$af ; a blue block ldb #$af ; a blue block
ldx tickp ; get position ldx tickp ; get position
stb ,x+ ; print it to screen buffer stb ,x+ ; print it to screen buffer
stx tickp ; and save position stx tickp ; and save position
out@ puls d,x,pc out@ puls d,x,pc
;;; Code to work with the CocoSDC
;;; Loosely based off of example code in the CoCo SDC Command Reference
;;; sdcPoll - Poll SDC Status
;;; Return X, 0-NotReady, Busy, or Error
;;; B - not saved
sdcPoll
ldx #$FFFF
sdcLoop ldb SDCSTAT
bmi sdcPErr ; error
lsrb
bcc sdcPRtn ; !busy
lsrb
bcs sdcPRtn ; ready
leax -1,x
bne sdcLoop
sdcPRtn rts
sdcPErr ldx #0
rts
;; sdcDone - return sdc to fdc mode
sdcDone
clr SDCLTCH
rts
;; sdcAbrt - return to basic
sdcAbrt
bsr sdcDone
lbra abort
;; sdcCmd - send command to sdc
;; input- A-cmd
;; scratched: b,x
sdcCmd
ldb #$43
stb SDCLTCH ; put CocoSDC in command mode
bsr sdcPoll ; wait for !busy
cmpx #0
beq sdcAbrt
cmdRdy sta SDCCREG ; send command
rts
;; sdcData - send data to sdc
;; Y - address of 256 bytes to send
;; scratched: d,x
strEnd RMB 2
sdcData
bsr sdcPoll ; wait for ready
cmpx #0
beq sdcAbrt
txRdy tfr y,d
addd #256
std strEnd ; data is always 256 bytes
txLoop cmpy strEnd
beq txCheck ; done sending data
ldd ,y++
std SDCDATA ; send data
bra txLoop
txCheck bsr sdcPoll ; wait for !busy
cmpx #0
beq sdcAbrt
txDone rts
;;; Tell the CocoSDC to load FUZIXFS.DSK
;; Y - address of 256 bytes to send
mountFs
lda #$E0
bsr sdcCmd ; Send CocoSDC Mount Command
bsr sdcData ; Send name of image to mount
bsr sdcDone ; Tell CocoSDC to return to emulation mode
rts
end start end start
 End of changes. 29 change blocks. 
16 lines changed or deleted 242 lines changed or added

This html diff was produced by rfcdiff 1.45. The latest version is available from http://tools.ietf.org/tools/rfcdiff/