From e2ba8458a5cfdfacfaf103e7ba97d610afa6c970 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 29 Aug 2022 16:11:13 -0400 Subject: initial commit --- fendersdbl.dasm | 411 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 fendersdbl.dasm (limited to 'fendersdbl.dasm') 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 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 ; 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 ; 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 + .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 +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 ; "." -- cgit v1.2.3