aboutsummaryrefslogtreecommitdiff
path: root/fendersdbl.dasm
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2022-08-29 16:11:13 -0400
committerB. Watson <urchlay@slackware.uk>2022-08-29 16:11:13 -0400
commite2ba8458a5cfdfacfaf103e7ba97d610afa6c970 (patch)
treecd665e602e6e2b636578a7d3d7894380605dafcc /fendersdbl.dasm
downloadbw-atari8-tools-e2ba8458a5cfdfacfaf103e7ba97d610afa6c970.tar.gz
initial commit
Diffstat (limited to 'fendersdbl.dasm')
-rw-r--r--fendersdbl.dasm411
1 files changed, 411 insertions, 0 deletions
diff --git a/fendersdbl.dasm b/fendersdbl.dasm
new file mode 100644
index 0000000..cb6ea3f
--- /dev/null
+++ b/fendersdbl.dasm
@@ -0,0 +1,411 @@
+; Fenders "3-sector" loader disassembly, 20070526 bkw
+; Double-density version
+
+; Note: the double-density loader doesn't actually fit in 3 sectors.
+; It uses sectors 1-3 and 720.
+; First 3 sectors of a DD disk are still only 128 bytes/sector.
+
+; At boot, the OS boot code loads the first 3 sectors and jumps to
+; the loaded code... which then loads sector 720 (a proper 256-byte DD
+; sector), which contains the rest of the code.
+
+; I haven't done a very thorough job of reverse-engineering the DD
+; version of the loader. Its structure is similar to that of the SD
+; loader (fenders.dasm).
+
+ processor 6502
+
+;;; Equates:
+
+;; OS ROM entry points
+SIOV .equ $e459
+COLDSV .equ $e477
+KEYBDV .equ $e420 ; K: handler device table
+keyb_get_lo .equ KEYBDV+4 ; pointer to "get byte" routine, minus 1
+keyb_get_hi .equ KEYBDV+5 ; (used by get_key)
+
+;; OS zero page
+BOOTQ .equ $09
+SAVMSC .equ $58
+ZROFRE .equ $80
+
+;; OS and FMS page 2 RAM variables
+COLDST .equ $0244
+SDMCTL .equ $022f
+SDLSTL .equ $0230
+SDLSTH .equ $0231
+RUNAD .equ $02e0
+INITAD .equ $02e2
+
+;; DCB, used for sector I/O parameters by SIOV (called by read_sector)
+DDEVIC .equ $0300
+DUNIT .equ $0301
+DCOMND .equ $0302
+DSTATS .equ $0303
+DBUFLO .equ $0304
+DBUFHI .equ $0305
+DTIMLO .equ $0306
+DBYTLO .equ $0308
+DBYTHI .equ $0309
+DAUX1 .equ $030a
+DAUX2 .equ $030b
+
+;; Hardware registers
+COLPF1 .equ $d017
+VCOUNT .equ $d40b
+
+;; Local variables (zero page)
+end_address .equ $45
+save_pos .equ $49
+menu_counter .equ $b0
+dir_sector_lo .equ $b1
+tmp_dlistl .equ $b2
+tmp_dlisth .equ $b3
+menu_ptr_lo .equ $b4
+menu_ptr_hi .equ $b5
+dest_ptr .equ $43
+start_sector_lo_tbl .equ $c0
+start_sector_hi_tbl .equ $e0
+
+;; Local variables (non zero page)
+buffer .equ $0b10
+sector_link_hi .equ $0c0d ; buffer + $fd
+sector_link_lo .equ $0c0e ; buffer + $fe
+sector_byte_count .equ $0c0f ; buffer + $ff
+
+;;; Bootable disk image starts here:
+ .org $0700
+
+;;; Standard Atari boot disk header (6 bytes)
+boot_record:
+ .byte $00 ; ignored
+ .byte $03 ; number of sectors to read
+ .word boot_record ; load address
+ .word COLDSV ; init address, don't think this gets used
+
+;;; Actual code starts here:
+boot_continuation:
+OFFSET_COLDST_1_DD .equ *-boot_record+1
+OFFSET_COLDST_2_DD .equ *-boot_record+5
+ LDY #$00 ; 0 .
+ STY COLDST
+ INY
+ STY BOOTQ
+ STY DUNIT
+ DEC DTIMLO
+set_dbl_density:
+ LDA #$4e ; 78 N
+ STA DCOMND
+ LDA #$40 ; 64 @
+ STA DSTATS
+ LDA #$0c ; 12 .
+ STA DBYTLO
+ LDA #$00 ; 0 .
+ STA DBYTHI
+ LDA #<buffer
+ STA DBUFLO
+ LDA #>buffer
+ STA DBUFHI
+ JSR SIOV
+ BMI set_dbl_density
+ LDA #$04 ; 4 .
+ STA buffer+5
+ LDA #$01 ; 1 .
+ STA buffer+6
+ LDA #$00 ; 0 .
+ STA buffer+7
+ LDA #$4f ; 79 O
+ STA DCOMND
+ LDA #$80 ; 128 .
+ STA DSTATS
+ JSR SIOV
+ BMI set_dbl_density
+
+; The bootloader code is 640 bytes long. First 384 bytes were loaded
+; from the 3 boot sectors already; the rest lives in sector 720, which
+; we have to load before running it:
+read_sec_720:
+ LDA #$52 ; 82 R
+ STA DCOMND
+ LDA #$40 ; 64 @
+ STA DSTATS
+ LDA #$80 ; 128 .
+ STA DBUFLO
+ LDA #$08 ; 8 .
+ STA DBUFHI
+ LDA #$00 ; 0 .
+ STA DBYTLO
+ LDA #$01 ; 1 .
+ STA DBYTHI
+ LDA #$d0 ; 208 .
+ STA DAUX1
+ LDA #$02 ; 2 .
+ STA DAUX2
+ JSR SIOV
+ BMI read_sec_720
+
+ ; setup display list
+ LDA SDLSTL
+ STA tmp_dlistl
+ LDA SDLSTH
+ STA tmp_dlisth
+ LDA #$00 ; 0 .
+ STA SDMCTL
+ LDA #<display_list ; 58 :
+ STA SDLSTL
+ LDA #>display_list ; 9 .
+ STA SDLSTH
+
+ ; init menu
+ LDA #$6c ; 108 l
+ STA menu_ptr_lo
+ LDA #$09 ; 9 .
+ STA menu_ptr_hi
+ LDA #$69 ; 105 i
+ STA dir_sector_lo
+
+read_dir_sector:
+ LDA dir_sector_lo
+ STA DAUX1
+ LDA #$01 ; 1 .
+ STA DAUX2
+ JSR read_sector
+ INC dir_sector_lo
+ DEX
+
+do_dirent:
+ LDA buffer,X
+ BEQ dir_done
+ BMI next_dirent
+ AND #$01 ; 1 .
+ BNE next_dirent
+ INC menu_counter
+ LDY menu_counter
+ LDA buffer+3,X
+ STA start_sector_lo_tbl,Y
+ LDA buffer+4,X
+ STA start_sector_hi_tbl,Y
+ TYA
+ CLC
+ ADC #$a0 ; 160 .
+ LDY #$03 ; 3 .
+ STA (menu_ptr_lo),Y
+ INY
+ LDA #$8e ; 142 .
+ STA (menu_ptr_lo),Y
+ INY
+next_char:
+ INY
+ LDA buffer+5,X
+ INX
+ SEC
+ SBC #$20 ; 32
+ STA (menu_ptr_lo),Y
+ CPY #$10 ; 16 .
+ BNE next_char
+ CLC
+ LDA menu_ptr_lo
+ ADC #$14 ; 20 .
+ STA menu_ptr_lo
+ BCC skip_ptr_hi
+ INC menu_ptr_hi
+skip_ptr_hi:
+ LDA menu_counter
+ CMP #$14 ; 20 .
+ BEQ dir_done
+next_dirent:
+ TXA
+ AND #$f0 ; 240 .
+ CLC
+ ADC #$10 ; 16 .
+ TAX
+ ASL
+ BCC do_dirent
+ BCS read_dir_sector
+dir_done:
+ LDA #$22 ; 34 "
+ STA SDMCTL
+wait_vcount_0:
+ LDA VCOUNT
+ BNE wait_vcount_0
+wait_for_input:
+ JSR get_key
+ SEC
+ SBC #$40 ; 64 @
+ CMP menu_counter
+ BEQ load_file
+ BCS wait_for_input
+load_file:
+ TAX
+ LDA start_sector_lo_tbl,X
+ STA DAUX1
+ LDA start_sector_hi_tbl,X
+ STA DAUX2
+ LDA #$68 ; 104 h
+ STA menu_ptr_lo
+ LDA #$09 ; 9 .
+ STA menu_ptr_hi
+L0834:
+ DEX
+ BEQ print_loading_msg
+ CLC
+ LDA menu_ptr_lo
+ ADC #$14 ; 20 .
+ STA menu_ptr_lo
+ BCC L0834
+ INC menu_ptr_hi
+ BNE L0834
+print_loading_msg:
+ LDY #$00 ; 0 .
+next_msg_byte:
+ LDA loading_msg,Y
+ STA (SAVMSC),Y
+ INY
+ CPY #$09 ; 9 .
+ BNE next_msg_byte
+print_filename:
+ LDA (menu_ptr_lo),Y
+ STA (SAVMSC),Y
+ INY
+ CPY #$15 ; 21 .
+ BNE print_filename
+ LDA #$00 ; 0 .
+ STA SDMCTL
+ LDA tmp_dlistl
+ STA SDLSTL
+ LDA tmp_dlisth
+ STA SDLSTH
+ LDA #$22 ; 34 "
+ STA SDMCTL
+wait_vcount_again:
+ LDA VCOUNT
+ BNE wait_vcount_again
+ LDY #$00 ; 0 .
+ TYA
+clear_zp:
+ STA ZROFRE,Y
+ INY
+ BPL clear_zp
+
+; the "JSR try_read" below MUST be located at $087f.
+; The JSR opcode is the last byte loaded in the 3-sector boot loader,
+; and its operand is the first 2 bytes loaded from sector 720!
+ .if *<>$087f
+ .echo "Code offsets have changed, fix me (", *, "should be $087f)"
+ .err
+ .endif
+ JSR try_read ; cut here!
+
+ DEX
+
+read_segment:
+ JSR get_next_byte
+ STA dest_ptr
+ JSR get_next_byte
+ STA dest_ptr+1
+ AND dest_ptr
+ CMP #$ff ; 255 .
+ BEQ read_segment
+ JSR get_next_byte
+ STA end_address
+ JSR get_next_byte
+ STA end_address+1
+load_byte:
+ JSR get_next_byte
+ STA (dest_ptr),Y
+ INC dest_ptr
+ BNE check_seg_done
+ INC dest_ptr+1
+ BEQ check_for_init
+check_seg_done:
+ LDA end_address
+ CMP dest_ptr
+ LDA end_address+1
+ SBC dest_ptr+1
+ BCS load_byte
+check_for_init:
+ LDA INITAD
+ ORA INITAD+1
+ BEQ read_segment
+ STX save_pos
+ JSR do_init
+ LDX save_pos
+ LDY #$00 ; 0 .
+ STY INITAD
+ STY INITAD+1
+ BEQ read_segment
+
+do_init:
+ JMP (INITAD)
+
+get_next_byte:
+ ; self-modifying code changes immediate CPX operand
+ CPX #$fd ; 253 .
+ BNE return_next_byte
+ LDA DAUX1
+ ORA DAUX2
+ BNE try_read
+OFFSET_SCREENOFF_DD .equ *-boot_record
+ LDA SDMCTL
+ JMP (RUNAD)
+
+read_sector:
+ LDA #$31 ; 49 1
+ STA DDEVIC
+ LDA #$52 ; 82 R
+ STA DCOMND
+ LDA #<buffer ; 16 .
+ STA DBUFLO
+ LDA #>buffer ; 11 .
+ STA DBUFHI
+ LDA #$00 ; 0 .
+ STA DBYTLO
+ LDA #$01 ; 1 .
+ STA DBYTHI
+
+try_read:
+ LDA #$40 ; 64 @
+ STA DSTATS
+ JSR SIOV
+ BMI try_read
+ LDA sector_link_hi
+ AND #$03 ; 3 .
+ STA DAUX2
+ LDA sector_link_lo
+ STA DAUX1
+OFFSET_ROTCOLOR_DD .equ *-boot_record
+ LDA COLPF1
+ LDA sector_byte_count
+ STA get_next_byte+1
+ LDY #$00 ; 0 .
+ LDX #$00 ; 0 .
+return_next_byte:
+ LDA buffer,X
+ INX
+ RTS
+
+get_key:
+ LDA keyb_get_hi
+ PHA
+ LDA keyb_get_lo
+ PHA
+ RTS
+
+loading_msg:
+ .byte $00,$00,$2c,$6f,$61,$64,$69,$6e ; "..,oadin"
+ .byte $67,$00,$00 ; "g.."
+display_list:
+ .byte $70,$70,$70,$47 ; "pppG"
+ .byte <screen,>screen
+ .byte $70,$06,$06,$06,$06,$06,$06 ; "p......"
+ .byte $06,$06,$06,$06,$06,$06,$06,$06 ; "........"
+ .byte $06,$06,$06,$06,$06,$06,$41 ; "......A"
+ .byte <display_list,>display_list
+OFFSET_TITLE_DD .equ *-boot_record
+screen:
+ .byte $00,$00,$00,$00,$61,$74,$61 ; ".....ata"
+ .byte $72,$69,$00,$61,$72,$63,$61,$64 ; "ri.arcad"
+ .byte $65,$00,$00,$00,$00,$00,$00,$00 ; "e......."
+ .byte $00,$00,$00,$00,$00,$00,$00,$00 ; "........"
+ .byte $00,$00,$00,$00,$00,$00,$00,$00 ; "........"
+ .byte $00 ; "."