; ================================================================================ ; Monroe OC8820 Boot ROM Disassembly - Version R3.00C ; ================================================================================ ; Original file: monroe_oc8820_boot_prom_r3_00C_tms2516_ea751e22.bin ; ROM Type: TMS2516 (2KB EPROM) ; Disassembler: z80dasm 1.1.6 ; ; This is the boot ROM for the Monroe OC8820 computer system. ; The system uses a Z80 CPU with bank-switched memory architecture. ; ; Memory Map: ; 0x0000-0x07FF : Boot ROM (this code) ; 0x3000-0x3FFF : Display memory ; 0xC000-0xFFFF : Banked RAM (controlled by I/O ports) ; 0xFF80-0xFFFF : System variables area ; ; I/O Port Map: ; 0x78-0x7B : Hard disk controller (DMA-based) ; 0xA0 : DART A (Dual Async Receiver/Transmitter) - Channel A data (printer) ; 0xA1 : DART A (Dual Async Receiver/Transmitter) - Channel A command ; 0xA2 : DART B (Dual Async Receiver/Transmitter) - Channel B data (keyboard) ; 0xA3 : DART B (Dual Async Receiver/Transmitter) - Channel B command ; 0xA4 : SIO A (Serial I/O) - Channel A data (comm) ; 0xA5 : SIO A (Serial I/O) - Channel A command ; 0xA6 : SIO B (Serial I/O) - Channel B data (RS-232C) ; 0xA7 : SIO B (Serial I/O) - Channel B command ; 0xA8 : CTC (Counter Timer Circuit) - Channel 0 (Communications baud) ; 0xA9 : CTC Channel 1 (AUX RS-232C baud) ; 0xAA : CTC Channel 2 (Printer baud) ; 0xAB : CTC Channel 3 ; 0xB0-0xB3 : Floppy disk controller (WD179x family) ; 0xB0: Status/Command, 0xB2: Sector, 0xB3: Track ; 0xB4-0xB5 : Z80 PIO A data and control ports ; 0xB4: PIO A data (floppy INTRQ signal, DMA control), 0xB5: PIO A control ; 0xB8-0xB9 : CRT controller (6845 CRTC) ; 0xB8: Register select, 0xB9: Data ; 0xC0 : Floppy drive selection and control ; 0xC4 : Program map A base address (memory banking) ; 0xC5 : Program map B base address (memory banking) ; 0xC6 : DMA map A base address (floppy DMA control) ; 0xC7 : DMA map B base address (hard disk DMA control) ; 0xC8 : Map and system control register (banking enable/disable) ; 0xD4-0xD8 : Graphics and color control ; 0xFF : Hardware detection port ; ; Boot Device Selection System: ; The Monroe OC8820 features sophisticated multi-device boot capability: ; ; 1. HARDWARE AUTO-DETECTION (Port 0xFF): ; - Reading 0 = Floppy-only configuration ; - Reading 1 = Hard disk + floppy configuration ; - Reading 2+ = Advanced hard disk configuration ; ; 2. BOOT PRIORITY ORDER: ; - HARD DISK FIRST (when detected): Uses DMA controller at ports 0x78-0x7B ; - FLOPPY FALLBACK: Uses WD179x controller at ports 0xB0-0xB3 (PIO A at 0xB4-0xB5) ; - Systematic retry: Tests floppy drives 0-3 with 8 total attempts ; - Final recovery: Special commands 0x10/0x11 on Drive 0 only ; ; 3. DUAL OPERATING SYSTEM SUPPORT: ; - Monroe OS8 (proprietary system) ; - CP/M (industry standard) ; - Boot path selection via calculated jumps at 0x05D0 ; ; Communication Specifications: ; DART A & B : High-speed serial (baud rate depends on system clock) ; SIO A & B : High-speed serial (same rate as DART ports) ; Printer Port : Lower-speed serial/parallel (baud rate depends on system clock) ; CTC Timing : Ch0/1: ÷16 prescaler, time const 3; Ch2: ÷256 prescaler, time const 78 ; Number of memory banks to test ; CRT Display : 80 characters/line text mode (184 total horizontal timing) ; ================================================================================ ; Constants displaymem: equ 0x3000 ; Start of display memory nomemchecks: equ 9 ; Number of memory banks to test (1-9) org 00000h ; ================================================================================ ; RESET VECTOR AND BOOT SEQUENCE ; ================================================================================ ; Z80 starts execution here after reset l0000h: di ;0000 Disable interrupts during boot ld sp,0ffa6h ;0001 Initialize stack pointer (top of RAM minus workspace) xor a ;0004 Clear A register (A=0) jp l_init ;0005 Jump to main initialization routine ; ================================================================================ ; DISPLAY MESSAGE ROUTINE ENTRY POINT ; ================================================================================ ; This routine is called to display text messages on screen ; Entry: DE = screen position, HL = message address ; Message format: first byte = length, followed by ASCII text display_entry: ld de,0303eh ;0008 Default screen position (row 3, col 62?) call cleartopline ;000b Clear the top line of display nop ;000e Padding nop ;000f Padding pop hl ;0010 Get return address (points to message) displaymsg: ld c,(hl) ;0011 Load message length from first byte inc hl ;0012 Point to message text ld b,000h ;0013 Clear B (BC now = message length) jp printroutine ;0015 Jump to print routine ; ================================================================================ ; RST VECTOR TABLE (0x0018-0x003F) ; ================================================================================ ; All RST vectors point to RST 38h (0x0038) - likely a common error handler ; The Z80 RST instructions provide fast calls to these addresses rst 38h ;0018 RST 18h -> RST 38h rst 38h ;0019 rst 38h ;001a rst 38h ;001b rst 38h ;001c rst 38h ;001d rst 38h ;001e rst 38h ;001f rst 38h ;0020 RST 20h -> RST 38h rst 38h ;0021 rst 38h ;0022 rst 38h ;0023 rst 38h ;0024 rst 38h ;0025 rst 38h ;0026 rst 38h ;0027 rst 38h ;0028 RST 28h -> RST 38h rst 38h ;0029 rst 38h ;002a rst 38h ;002b rst 38h ;002c rst 38h ;002d rst 38h ;002e rst 38h ;002f rst 38h ;0030 RST 30h -> RST 38h rst 38h ;0031 rst 38h ;0032 rst 38h ;0033 rst 38h ;0034 rst 38h ;0035 rst 38h ;0036 rst 38h ;0037 rst 38h ;0038 RST 38h - Common error handler rst 38h ;0039 rst 38h ;003a rst 38h ;003b rst 38h ;003c rst 38h ;003d rst 38h ;003e rst 38h ;003f ; ================================================================================ ; WARM BOOT AND RESTART VECTORS ; ================================================================================ jp l0000h ;0040 Warm boot - restart system jp l0000h ;0043 Another restart vector ; ================================================================================ ; MAIN SYSTEM INITIALIZATION ; ================================================================================ ; This routine initializes all I/O controllers and system hardware l_init: out (0c0h),a ;0046 Clear floppy disk controller out (0c4h),a ;0048 Clear Program map A base address out (0c5h),a ;004a Clear Program map B base address out (0c6h),a ;004c Clear DMA map A base address out (0c7h),a ;004e Clear DMA map B base address out (0d4h),a ;0050 Clear Hi-res color control out (0d8h),a ;0052 Clear Hi-res graphics start address ld hl,PIOA_start ;0054 Point to I/O initialization data table jp l0562h ;0057 Jump to OTIR routine to initialize peripherals ; ================================================================================ ; I/O CONTROLLER INITIALIZATION DATA TABLE ; ================================================================================ ; This table contains initialization sequences for various Z80 peripheral chips ; Format: Port address, Count, Data bytes... ; Used by OTIR routine at 0562h ; BLOCK 'PIOA' (start 0x005a end 0x008b) PIOA_start: ; CRT Controller initialization (6845 compatible) defb 0b5h ;005a I/O port: CRT register select defb 004h ;005b Count: 4 bytes to follow defb 0cfh ;005c Reg 0: Horizontal Total = 207+1=208 chars/line defb 0b8h ;005d Reg 1: Horizontal Displayed = 184 (likely 80 char mode with wide timing) defb 037h ;005e Reg 2: Horizontal Sync Position = 55 (after visible) defb 0efh ;005f Reg 3: Sync Width = V:14 lines, H:15 chars ; PIO A Data Port defb 0b4h ;0060 I/O port: PIO A data defb 001h ;0061 Count: 1 byte to follow defb 001h ;0062 Data: Enable something ; DART A (Serial port A) initialization defb 0a1h ;0063 I/O port: DART A command defb 006h ;0064 Count: 6 bytes to follow defb 048h ;0065 Reset command defb 048h ;0066 Reset command (double reset) defb 004h ;0067 Write register 4: Clock/format control defb 044h ;0068 16x clock, 1 stop bit, no parity defb 005h ;0069 Write register 5: Transmit control defb 0eah ;006a DTR active, RTS active, Tx enable, 8 bits ; DART B (Serial port B) initialization defb 0a3h ;006b I/O port: DART B command defb 008h ;006c Count: 8 bytes to follow defb 048h ;006d Reset command defb 048h ;006e Reset command (double reset) defb 004h ;006f Write register 4: Clock/format control defb 044h ;0070 16x clock, 1 stop bit, no parity defb 001h ;0071 Write register 1: Interrupt control defb 000h ;0072 No interrupts enabled defb 003h ;0073 Write register 3: Receive control defb 0c1h ;0074 Rx enable, 8 bits per char ; SIO A (Serial I/O A) initialization defb 0a5h ;0075 I/O port: SIO A command defb 002h ;0076 Count: 2 bytes to follow defb 048h ;0077 Reset command defb 048h ;0078 Reset command (double reset) ; SIO B (Serial I/O B) initialization defb 0a7h ;0079 I/O port: SIO B command defb 002h ;007a Count: 2 bytes to follow defb 048h ;007b Reset command defb 048h ;007c Reset command (double reset) ; CTC (Counter Timer Circuit) initialization ; Used to generate baud rate clocks for serial communications ; CTC Channel 0 - Communications baud rate generator defb 0a8h ;007d I/O port: CTC CHANNEL 0 defb 002h ;007e Count: 2 bytes to follow defb 003h ;007f Control: Timer mode, prescaler 16, auto-trigger defb 003h ;0080 Time constant: 3 (high-speed rate) ; CTC Channel 1 - Auxiliary RS-232C baud rate generator defb 0a9h ;0081 I/O port: CTC CHANNEL 1 defb 002h ;0082 Count: 2 bytes to follow defb 003h ;0083 Control: Timer mode, prescaler 16, auto-trigger defb 003h ;0084 Time constant: 3 (same rate as channel 0) ; CTC Channel 2 - Printer baud rate generator defb 0aah ;0085 I/O port: CTC CHANNEL 2 defb 002h ;0086 Count: 2 bytes to follow defb 057h ;0087 Control: Timer mode, prescaler 256, auto-trigger defb 04eh ;0088 Time constant: 78 (slower rate for printer) ; End of I/O initialization table defb 000h ;0089 Terminator: port 0 (invalid) defb 000h ;008a Terminator: count 0 PIOA_end: ld ix,initcontinue ;008b Set continuation address after screen setup jp setupclearscreen ;008f Initialize display and clear screen ; ================================================================================ ; INITIALIZATION CONTINUATION ; ================================================================================ ; Returns here after display is initialized and cleared initcontinue: ld a,080h ;0092 Enable hi-res graphics, disable buzzer out (0d4h),a ;0094 Write to hi-res color control register ld de,displaymem ;0096 Point to start of display memory ld hl,TESTING_start ;0099 Point to "Testing." message jp displaymsg ;009c Display the message ; ================================================================================ ; "TESTING." MESSAGE DATA ; ================================================================================ ; BLOCK 'TESTING' (start 0x009f end 0x00a8) TESTING_start: defb 008h ;009f Message length: 8 characters defb 054h ;00a0 'T' defb 065h ;00a1 'e' defb 073h ;00a2 's' defb 074h ;00a3 't' defb 069h ;00a4 'i' defb 06eh ;00a5 'n' defb 067h ;00a6 'g' defb 02eh ;00a7 '.' TESTING_end: ; ================================================================================ ; MEMORY DETECTION AND TEST INITIALIZATION ; ================================================================================ ; This section detects memory size (128K vs 256K) and sets up memory testing ld a,005h ;00a8 DART B register 5 (transmit control) out (0a3h),a ;00aa Select register 5 ld a,068h ;00ac Enable transmit, 7 bits, no break out (0a3h),a ;00ae Configure DART B transmit ld a,0f0h ;00b0 Memory mapping control value out (0c8h),a ;00b2 Set map and system control register ld ix,0c001h ;00b4 Point to banked memory + 1 (0xC001) ld bc,00c5h ;00b8 BC = 0x00C5 (memory map port in C) ld d,nomemchecks ;00bb D = 9 (number of memory banks to test) ; Memory size detection routine ld a,0a0h ;00bd Test value for 256K detection out (0c5h),a ;00bf Set program map B base to 0xA0 ld (ix-001h),b ;00c1 Write test value (0x00) to 0xC000 dec b ;00c4 B = 0xFF inc a ;00c5 A = 0xA1 out (0c5h),a ;00c6 Set program map B base to 0xA1 ld (ix-001h),b ;00c8 Write 0xFF to 0xC000 in new bank dec a ;00cb A = 0xA0 (back to first bank) out (0c5h),a ;00cc Switch back to first bank ld b,(ix-001h) ;00ce Read back value from 0xC000 inc b ;00d1 Increment (0x00 becomes 0x01) jr z,skip256 ;00d2 If zero, we have 256K (0xFF+1=0x00) ld d,011h ;00d4 If not zero, set to test 17 banks (256K) skip256: ld b,d ;00d6 B = number of banks to test ld hl,memtesteval ;00d7 Point to memory test bank list ld de,0000h ;00da Clear error counters ; ================================================================================ ; MAIN MEMORY TEST LOOP ; ================================================================================ ; Tests each memory bank using rotating bit patterns beginmemtest: outi ;00dd Switch memory bank: output (HL) to port C(0xC5), HL++, B-- jr z,memcmp ;00df If B=0, all banks tested - check results exx ;00e1 Switch to alternate register set ld b,055h ;00e2 Start with test pattern 0x55 (01010101) ld e,000h ;00e4 Clear local error accumulator ; Test loop for current memory bank using rotating patterns memtestloop: ld hl,0c000h ;00e6 Start of current memory bank ld c,b ;00e9 Copy test pattern to C ; Write test pattern to entire 16K bank memtestwriteloop: ld (hl),c ;00ea Write pattern to memory rlc c ;00eb Rotate pattern left (01010101 -> 10101010) inc l ;00ed Next byte (low address) jr nz,memtestwriteloop ;00ee Continue until L wraps to 0 rlc c ;00f0 Rotate pattern again for next page inc h ;00f2 Next page (high address) jr nz,memtestwriteloop ;00f3 Continue until H wraps to 0 ; Read back and verify test pattern ld h,0c0h ;00f5 Reset to start of bank ld c,b ;00f7 Restore original test pattern memtestreadloop: ld a,(hl) ;00f8 Read memory location xor c ;00f9 Compare with expected pattern or e ;00fa Accumulate errors in E ld e,a ;00fb Store error accumulator rlc c ;00fc Rotate expected pattern inc l ;00fe Next byte jr nz,memtestreadloop ;00ff Continue until L wraps rlc c ;0101 Rotate pattern for next page inc h ;0103 Next page jr nz,memtestreadloop ;0104 Continue until H wraps rlc b ;0106 Rotate base pattern for next iteration jr nc,memtestloop ;0108 Continue if not back to original (8 patterns) ; Process test results for this bank ld a,e ;010a Get error accumulator exx ;010b Switch back to main register set and a ;010c Test for errors jr z,memgood ;010d No errors - bank is good inc a ;010f Check if all bits failed (0xFF -> 0x00) jr z,memerror ;0110 Complete failure - count as bad bank or d ;0112 Partial failure - OR with global error flags ld d,a ;0113 Store combined error status jr memgood ;0114 Continue testing memerror: inc e ;0116 Increment bad bank counter memgood: ld a,b ;0117 Check remaining bank count cp 004h ;0118 Is this bank 4? jr nz,beginmemtest ;011a If not bank 4, continue testing ld a,020h ;011c FDC control: Drive B select (dual drive system) out (0c0h),a ;011e Write to floppy controller control register jr beginmemtest ;0120 Continue memory testing ; ================================================================================ ; MEMORY BANK SELECTION TABLE ; ================================================================================ ; This table contains the bank values written to port 0xC5 (Program map B base) ; Each value maps a different 16K memory bank into the 0xC000-0xFFFF address space memtesteval: ; Memory bank mapping values defb 0a1h ;0122 Bank count: 161 (actually used as counter) defb 0c1h ;0123 Memory bank 0xC1 defb 0e1h ;0124 Memory bank 0xE1 defb 000h ;0125 Memory bank 0x00 defb 020h ;0126 Memory bank 0x20 defb 040h ;0127 Memory bank 0x40 defb 060h ;0128 Memory bank 0x60 defb 080h ;0129 Memory bank 0x80 defb 0a0h ;012a Memory bank 0xA0 (Start of 256KB test range) defb 0c0h ;012b Memory bank 0xC0 defb 0e0h ;012c Memory bank 0xE0 defb 001h ;012d Memory bank 0x01 defb 021h ;012e Memory bank 0x21 defb 041h ;012f Memory bank 0x41 defb 061h ;0130 Memory bank 0x61 defb 081h ;0131 Memory bank 0x81 ; ================================================================================ ; MEMORY TEST RESULTS EVALUATION ; ================================================================================ ; Check if memory test found any errors and decide next action nop memcmp: xor a ;0133 Clear A register or d ;0134 Check global error flags in D or e ;0135 Check bad bank count in E - Any errors? jr z,floppystart ;0136 If no errors, proceed to floppy boot ld ix,memcheckdisplay ;0138 Memory errors found - prepare error display jp setupcrt ;013c Jump to CRT setup for error display ; ================================================================================ ; MEMORY ERROR DISPLAY ROUTINE ; ================================================================================ memcheckdisplay: ld de,displaymem ;013f Point to display memory ld hl,ERROR2_start ;0142 Point to error message jp displaymsg ;0145 Display "Error #2 :Call service." ; ================================================================================ ; ERROR #2 MESSAGE DATA ; ================================================================================ ; BLOCK 'ERROR2' (start 0x0148 end 0x0160) ERROR2_start: defb 017h ;0148 Message length: 23 characters defb 045h ;0149 'E' - "Error #2 :Call service." defb 072h ;014a 'r' defb 072h ;014b 'r' defb 06fh ;014c 'o' defb 072h ;014d 'r' defb 020h ;014e ' ' defb 023h ;014f '#' defb 032h ;0150 '2' defb 020h ;0151 ' ' defb 03ah ;0152 ':' defb 043h ;0153 'C' defb 061h ;0154 'a' defb 06ch ;0155 'l' defb 06ch ;0156 'l' defb 020h ;0157 ' ' defb 073h ;0158 's' defb 065h ;0159 'e' defb 072h ;015a 'r' defb 076h ;015b 'v' defb 069h ;015c 'i' defb 063h ;015d 'c' defb 065h ;015e 'e' defb 02eh ;015f '.' ERROR2_end: halt ;0160 System halt - requires service intervention ; ================================================================================ ; FLOPPY DISK BOOT INITIALIZATION ; ================================================================================ ; Memory test passed - prepare for floppy disk boot floppystart: out (0c5h),a ;0161 Clear program map B base (A=0 from memcmp) out (0c8h),a ;0163 Clear map and system control (disable banking) dec hl ;0165 HL was pointing past end of memory test table dec hl ;0166 Move back to get the memory size indicator ld a,(hl) ;0167 Load memory configuration value floppystart2: rrca ;0168 Rotate right with carry to get MSB and 080h ;0169 Isolate bit 7 (128K vs 256K indicator) ld (0ff80h),a ;016b Store memory size flag: 0x80=256K, 0x00=128K ld de,0ffa6h ;016e Destination: high RAM workspace area ld hl,005beh ;0171 Source: ROM data block at 0x05BE ld bc,0005ah ;0174 Count: 90 bytes of runtime data ldir ;0177 Copy ROM constants to RAM workspace call setupclearscreen2 ;0179 Clear screen and setup display for boot ; ================================================================================ ; DISK BOOT SEQUENCE WITH AUTO-RETRY ; ================================================================================ ; ================================================================================ ; BOOT DEVICE DETECTION AND PRIORITY SYSTEM ; ================================================================================ ; Memory initialization complete - attempt to boot with device auto-detection ; ; BOOT PRIORITY ORDER: ; 1. Auto-detect controller type (port 0xFF) to determine available devices ; 2. If hard disk detected: Try hard disk FIRST (faster, larger capacity) ; 3. If hard disk fails or not present: Fall back to floppy disk drives ; 4. Try drives in order: Drive 0, 1, 2, 3 (up to 8 total attempts) readydiskloop: call readydisk ;017c Display "Ready For System Disk" message call sub_061ch ;017f *** CRITICAL *** Initialize disk controller & detect HDD vs floppy ld a,0ffh ;0182 Load 0xFF (default retry flag) jr c,skipinvert ;0184 Keep 0xFF if carry set (controller error - floppy only mode) cpl ;0186 Invert to 0x00 (normal operation - HDD detection successful) skipinvert: ld (0ff93h),a ;0187 Store boot device mode: 0xFF=floppy-only, 0x00=HDD+floppy available ld hl,00404h ;018a H=4 retries, L=4 track number? ld (0ff91h),hl ;018d Store retry count and track parameters or a ;0190 Test the boot device mode flag jr nz,l01c3h ;0191 If floppy-only mode (0xFF), skip HDD attempts, go to drive loop ; *** HARD DISK BOOT ATTEMPTS (when HDD controller detected) *** ; Normal boot mode: Try hard disk operations FIRST ld c,010h ;0193 Hard disk command 0x10 (seek track 0/recalibrate) call sub_065ah ;0195 Execute hard disk command through DMA jr c,l01abh ;0198 If HDD error, try alternate HDD command ld bc,00000h ;019a B=drive 0, C=track 0 (hard disk drive 0) call sub_040eh ;019d Attempt to read boot sector from hard disk jr c,l01abh ;01a0 If HDD read error, try alternate HDD approach call sub_03a2h ;01a2 Process successful HDD sector read ld a,(0ff8bh) ;01a5 Get boot validation result from HDD ld (0ff91h),a ;01a8 Store HDD boot result l01abh: ; *** ALTERNATE HARD DISK ATTEMPT *** ld c,011h ;01ab Hard disk command 0x11 (alternate seek/step command) call sub_065ah ;01ad Execute alternate hard disk command through DMA jr c,l01c3h ;01b0 If HDD command error, fall back to floppy drives ld bc,0000h ;01b2 B=drive 0, C=track 0 (hard disk drive 0) call sub_040eh ;01b5 Second attempt to read HDD boot sector jr c,l01c3h ;01b8 If HDD read still fails, fall back to floppy drives call sub_03a2h ;01ba Process successful HDD sector read ld a,(0ff8bh) ;01bd Get final HDD boot validation result ld (0ff92h),a ;01c0 Store HDD boot result flag ; ================================================================================ ; FLOPPY DRIVE FALLBACK AND DRIVE SELECTION LOOP ; ================================================================================ ; Reached when: 1) Hard disk not detected, 2) Hard disk boot failed, or 3) Force floppy mode ; Systematically tries all floppy drives (0-3) with multiple retry attempts l01c3h: ld a,001h ;01c3 Start with drive bit 0 (will create drive ID 0xA1) ld c,008h ;01c5 Retry counter: 8 attempts across all floppy drives driveloop: l01c7h: ; *** FLOPPY DRIVE SELECTION *** ; Drive encoding: 0xA1=Drive 0, 0xA2=Drive 1, 0xA4=Drive 2, 0xA8=Drive 3 or 0a0h ;01c7 OR with 0xA0 base: creates floppy controller commands out (0c0h),a ;01c9 Select floppy drive via port 0xC0 (different from HDD ports 0x78-0x7B) ld b,a ;01cb Save current drive select value ; Wait for floppy drive ready status l01cch: in a,(0b0h) ;01cc Read floppy controller status register (port 0xB0, not HDD 0x79) rr a ;01ce Rotate right - check busy bit (bit 0) into carry jr c,l01cch ;01d0 Loop while floppy drive is busy (bit 0 = 1) in a,(0b0h) ;01d2 Read floppy status again add a,a ;01d4 Shift left - check ready bit (bit 7) into carry jr c,l01ddh ;01d5 If floppy drive ready (bit 7 = 1), continue to next drive call delayloop ;01d7 Floppy drive not ready - wait a bit call loadingdisk ;01da Display "Loading..." and attempt boot from this floppy drive ; *** DRIVE ADVANCEMENT AND RETRY LOGIC *** l01ddh: inc c ;01dd Increment attempt counter (8 total attempts across all drives) ld a,b ;01de Restore drive select value from previous iteration add a,a ;01df Shift left to advance to next drive: 0xA1->0xA2->0xA4->0xA8 and 00fh ;01e0 Mask to keep only drive bits (removes 0xA0 base, leaves 1,2,4,8) jr nz,l01c7h ;01e2 Continue loop if more drives to try (bits 1,2,4,8 not all exhausted) ; ================================================================================ ; ALL FLOPPY DRIVES EXHAUSTED - FINAL FALLBACK ATTEMPTS ; ================================================================================ ; Reached when all floppy drives 0-3 have been tried and failed to boot ld a,(0ff93h) ;01e4 Load boot mode flag from memory or a ;01e7 Test if normal boot mode (0x00) or retry mode (0xFF) jr nz,l0204h ;01e8 If already in retry mode, skip to "No System Device" error in a,(0ffh) ;01ea Read hardware status port 0xFF (same port used for HDD detection) and 020h ;01ec Check bit 5 - unknown hardware condition/status jr nz,l0204h ;01ee If bit 5 set, skip directly to error message ; *** DESPERATE FINAL ATTEMPTS ON DRIVE 0 ONLY *** ; Special recovery commands specifically for Drive 0 as last resort ld c,010h ;01f0 Load floppy command 0x10 (likely recalibrate/restore) call sub_065ah ;01f2 Execute floppy controller command ld b,000h ;01f5 Force selection of Drive 0 specifically call nc,loadingdisk ;01f7 If command succeeded (no carry), try loading from Drive 0 ld c,011h ;01fa Load floppy command 0x11 (likely seek home/step in) call sub_065ah ;01fc Execute second recovery command ld b,000h ;01ff Force Drive 0 selection again call nc,loadingdisk ;0201 If command succeeded, make final boot attempt from Drive 0 ; ================================================================================ ; BOOT FAILURE - DISPLAY ERROR AND RESTART BOOT SEQUENCE ; ================================================================================ l0204h: call setupclearscreen2 ;0204 Clear screen and setup display for error ld bc,002a3h ;0207 B=2 bytes, C=0xA3 port (memory control?) ld hl,0061ah ;020a Source: ROM data at 0x061A otir ;020d Output 2 bytes to port 0xA3 (setup display controller) ld de,03000h ;020f Display memory base address ld hl,NOSYSTEM_start ;0212 Point to "No System Device On Line." message jp displaymsg ;0215 Display error message and wait ; ================================================================================ ; "NO SYSTEM DEVICE ON LINE" MESSAGE AND RETRY LOOP ; ================================================================================ ; BLOCK 'NOSYSTEM' (start 0x0218 end 0x0232) NOSYSTEM_start: defb 019h ;0218 Message length: 25 characters defb 04eh ;0219 'N' - "No System Device On Line." defb 06fh ;021a 'o' defb 020h ;021b ' ' defb 053h ;021c 'S' defb 079h ;021d 'y' defb 073h ;021e 's' defb 074h ;021f 't' defb 065h ;0220 'e' defb 06dh ;0221 'm' defb 020h ;0222 ' ' defb 044h ;0223 'D' defb 065h ;0224 'e' defb 076h ;0225 'v' defb 069h ;0226 'i' defb 063h ;0227 'c' defb 065h ;0228 'e' defb 020h ;0229 ' ' defb 04fh ;022a 'O' defb 06eh ;022b 'n' defb 020h ;022c ' ' defb 04ch ;022d 'L' defb 069h ;022e 'i' defb 06eh ;022f 'n' defb 065h ;0230 'e' defb 02eh ;0231 '.' NOSYSTEM_end: call delayloop ;0232 Wait for user to see message (~1 second) call delayloop ;0235 Additional delay (~1 second) call delayloop ;0238 Final delay (~1 second, total ~3 seconds) jp readydiskloop ;023b Restart entire boot sequence - infinite retry loop! ; ================================================================================ ; CRITICAL ERROR HANDLER - SYSTEM HALT ; ================================================================================ ; This routine is called for fatal hardware errors that require service l023eh: ld ix,returnsetupcrt1 ;023e Setup return address for CRT initialization jp setupcrt ;0242 Initialize CRT controller and return here returnsetupcrt1: call screenclearnetry2 ;0245 Clear screen and setup for error display rst 10h ;0248 RST 10h: Display message routine ; ================================================================================ ; ERROR #0 MESSAGE DATA ; ================================================================================ ; BLOCK 'ERROR0' (start 0x0249 end 0x0261) ERROR0_start: defb 017h ;0249 Message length: 23 characters defb 045h ;024a 'E' - "Error #0: Call service." defb 072h ;024b 'r' defb 072h ;024c 'r' defb 06fh ;024d 'o' defb 072h ;024e 'r' defb 020h ;024f ' ' defb 023h ;0250 '#' defb 030h ;0251 '0' defb 03ah ;0252 ':' defb 020h ;0253 ' ' defb 043h ;0254 'C' defb 061h ;0255 'a' defb 06ch ;0256 'l' defb 06ch ;0257 'l' defb 020h ;0258 ' ' defb 073h ;0259 's' defb 065h ;025a 'e' defb 072h ;025b 'r' defb 076h ;025c 'v' defb 069h ;025d 'i' defb 063h ;025e 'c' defb 065h ;025f 'e' defb 02eh ;0260 '.' ERROR0_end: halt ;0261 System halt - requires service call ; ================================================================================ ; DISK LOADING ROUTINE - MAIN BOOT SECTOR LOADER ; ================================================================================ ; This routine displays "Loading" message and attempts to load the boot sector ; Input: B = drive number (0-3) ; Uses: All registers, modifies disk parameters at 0xFF81-0xFF82 loadingdisk: push bc ;0262 Save BC (drive number and parameters) xor a ;0263 Clear A register (A = 0) ld (0ff81h),a ;0264 Clear disk status parameter 1 ld (0ff82h),a ;0267 Clear disk status parameter 2 rst 8 ;026a RST 8: Display message routine ; ================================================================================ ; "LOADING " MESSAGE DATA ; ================================================================================ ; BLOCK 'LOADING' (start 0x026b end 0x0274) LOADING_start: defb 008h ;026b Message length: 8 characters defb 04ch ;026c 'L' - "Loading " defb 06fh ;026d 'o' defb 061h ;026e 'a' defb 064h ;026f 'd' defb 069h ;0270 'i' defb 06eh ;0271 'n' defb 067h ;0272 'g' defb 020h ;0273 ' ' LOADING_end: pop ix ;0274 Restore IX from stack (return address) call sub_04a1h ;0276 Initialize disk controller and seek to track 0 jr c,l023eh ;0279 If seek error, jump to fatal error handler ld bc,0000h ;027b B=track 0, C=sector 0 (boot sector location) call sub_040eh ;027e Read boot sector from disk jr c,l02ddh ;0281 If read error, handle disk error ; Check disk status and system configuration ld hl,(0ff81h) ;0283 Load disk status parameters (2 bytes) ld a,l ;0286 Get low byte of status and a ;0287 Test if zero (no special conditions) jr z,l029ch ;0288 If zero, continue with normal boot process ld a,h ;028a Get high byte of status and 003h ;028b Mask bits 0-1 (configuration bits) in a,(0ffh) ;028d Read system status port 0xFF jr z,l0298h ;028f If masked value is zero, check bit 1 bit 0,a ;0291 Test bit 0 of system status jr nz,l029ch ;0293 If bit 0 set, continue normal boot l0295h: jp l034bh ;0295 Jump to alternate boot routine l0298h: bit 1,a ;0298 Test bit 1 of system status jr z,l0295h ;029a If bit 1 clear, jump to alternate boot routine l029ch: call sub_03a2h ;029c Process and validate boot sector data jp c,l0343h ;029f If validation failed (carry set), handle error jr z,l02b6h ;02a2 If zero flag set, skip additional sector read call sub_040eh ;02a4 Read additional sector data if needed jr c,l02ddh ;02a7 If read error, handle disk error ; ================================================================================ ; BOOT SECTOR VALIDATION AND EXECUTION SETUP ; ================================================================================ ; Boot sector successfully read - now validate and prepare for execution ld hl,0401fh ;02a9 Point to boot sector signature/validity location bit 0,(hl) ;02ac Check boot sector validity bit 0 jp nz,l034fh ;02ae If validity bit set, handle invalid boot sector call sub_040eh ;02b1 Read final sector data if needed jr c,l02ddh ;02b4 If read error, handle disk error l02b6h: exx ;02b6 Switch to alternate register set (BC',DE',HL') ld hl,0400eh ;02b7 Point to boot program load address in boot sector ld d,(hl) ;02ba Get high byte of load address inc hl ;02bb Move to next byte ld e,(hl) ;02bc Get low byte of load address push de ;02bd Save complete load address pop iy ;02be IY = target load address for boot program ld hl,04080h ;02c0 Point to boot sector parameter block ld c,(hl) ;02c3 Get boot parameter 1 inc hl ;02c4 Skip reserved byte inc hl ;02c5 Point to next parameter ld d,(hl) ;02c6 Get parameter high byte inc hl ;02c7 Move to next ld e,(hl) ;02c8 Get parameter low byte inc hl ;02c9 Move to next ld a,(hl) ;02ca Get additional parameter byte inc hl ;02cb Move to final parameter ld l,(hl) ;02cc Get final parameter byte ld h,a ;02cd Combine A and L into HL ex de,hl ;02ce Exchange DE and HL registers push hl ;02cf Save HL on stack ld a,e ;02d0 Get low byte for calculation add a,0ffh ;02d1 Add 255 (effectively subtract 1 with carry) ld a,d ;02d3 Get high byte exx ;02d4 Switch back to main register set ld e,000h ;02d5 E = 0 for addition adc a,e ;02d7 Add high byte with carry from previous operation ld d,a ;02d8 D = calculated high byte for sector loading pop hl ;02d9 Restore HL from stack (boot program parameters) call sub_0414h ;02da Load complete boot program from disk into memory ; ================================================================================ ; BOOT PROGRAM EXECUTION AND TRANSFER OF CONTROL ; ================================================================================ ; Boot program successfully loaded - now transfer control to the loaded code l02ddh: jr c,l0347h ;02dd If disk load error (carry set), handle error ld a,(0ff8bh) ;02df Get boot completion status flag cp 002h ;02e2 Check if status = 2 (special boot mode) jr z,l02eeh ;02e4 If special mode, use alternate execution path ; Standard boot execution: Transfer control to loaded program xor a ;02e6 Clear A register (A = 0) ex af,af' ;02e7 Save AF to alternate AF' register exx ;02e8 Switch to alternate register set jp 0ffa6h ;02e9 *** TRANSFER CONTROL TO LOADED BOOT PROGRAM! *** ; ================================================================================ ; ALTERNATE BOOT EXECUTION PATH ; ================================================================================ ; Special boot mode handling (status = 2) l02ech: ex af,af' ;02ec Restore AF from alternate register adc a,c ;02ed Add C with carry for parameter processing l02eeh: push ix ;02ee Save IX register (return address) pop bc ;02f0 BC = return address from IX ld a,(0ff8bh) ;02f1 Get boot completion status flag ld de,00013h ;02f4 DE = 0x0013 (parameter constant) ld hl,0ff8dh ;02f7 HL = system parameter storage area jr nz,l033fh ;02fa If status not zero, jump to error 0x33 cp 002h ;02fc Compare status with 2 (special boot mode) jp nz,0ffb8h ;02fe If not 2, jump to alternate boot entry point ; Special boot mode (status = 2) - setup system parameters push bc ;0301 Save return address bit 3,c ;0302 Test bit 3 of return address low byte jr nz,l030bh ;0304 If bit 3 set, skip disk flag setup ld a,0ffh ;0306 Set disk parameter flag ld (0ff81h),a ;0308 Store at disk parameter location l030bh: in a,(0ffh) ;030b Read system status port 0xFF ld c,a ;030d Save status in C xor a ;030e Clear A register (A = 0) bit 0,c ;030f Test bit 0 of system status jr z,l0315h ;0311 If bit 0 clear, skip ld a,00fh ;0313 Set A = 0x0F (enable low nibble) l0315h: bit 1,c ;0315 Test bit 1 of system status jr z,l031bh ;0317 If bit 1 clear, skip or 0f0h ;0319 Set high nibble (A |= 0xF0) l031bh: ld b,a ;031b B = combined system configuration mask ld a,(0ff81h) ;031c Get disk parameter flag cpl ;031f Complement (invert all bits) and a ;0320 Test if result is zero jr z,l0334h ;0321 If zero (was 0xFF), skip complex calculation ; Complex bit manipulation for drive/system configuration push bc ;0323 Save BC (config mask and status) push ix ;0324 Save IX pop bc ;0326 BC = IX (return address) ld a,c ;0327 Get low byte of return address sub 007h ;0328 Subtract 7 (adjust for calculation) ld b,a ;032a B = adjusted value ld a,080h ;032b Start with bit 7 set (0x80) ; Rotate bit pattern based on adjusted return address l032dh: rlca ;032d Rotate left with carry (shift bit pattern) rlca ;032e Rotate left again (2 positions per loop) djnz l032dh ;032f Decrement B and loop until B=0 pop bc ;0331 Restore BC (config mask and status) and b ;0332 Mask with configuration bits rrca ;0333 Rotate right once (adjust final position) l0334h: xor b ;0334 XOR with configuration mask pop bc ;0335 Restore original BC (return address) ld (0ff81h),a ;0336 Store final calculated system parameter ld a,(0ff8bh) ;0339 Get boot completion status jp 0ffb8h ;033c Jump to final boot entry point in RAM ; ================================================================================ ; BOOT ERROR CLASSIFICATION AND DISPLAY ; ================================================================================ ; Various boot errors are classified and appropriate error messages displayed l033fh: ld a,033h ;033f Error code 0x33 (51 decimal) - set error number jr l0351h ;0341 Jump to error display routine l0343h: ld a,030h ;0343 Error code 0x30 (48 decimal) - validation error jr l0351h ;0345 Jump to error display routine l0347h: ld a,032h ;0347 Error code 0x32 (50 decimal) - disk read error jr l0351h ;0349 Jump to error display routine l034bh: ld a,039h ;034b Error code 0x39 (57 decimal) - system configuration error jr l0351h ;034d Jump to error display routine l034fh: ld a,031h ;034f Error code 0x31 (49 decimal) - invalid boot sector ; Common error display routine - converts error code to display l0351h: push ix ;0351 Save IX register (return address) push af ;0353 Save error code on stack call screenclearnetry2 ;0354 Clear screen and setup display push de ;0357 Save DE register rst 10h ;0358 RST 10h: Display message routine ; ================================================================================ ; ERROR #10 MESSAGE DATA - INVALID SYSTEM DISK ; ================================================================================ ; BLOCK 'INVALID' (start 0x0359 end 0x0382) INVALID_start: defb 028h ;0359 Message length: 40 characters defb 045h ;035a 'E' - "Error #10: Invalid System Disk in Drive " defb 072h ;035b 'r' defb 072h ;035c 'r' defb 06fh ;035d 'o' defb 072h ;035e 'r' defb 020h ;035f ' ' defb 023h ;0360 '#' defb 031h ;0361 '1' defb 030h ;0362 '0' defb 03ah ;0363 ':' defb 020h ;0364 ' ' defb 049h ;0365 'I' defb 06eh ;0366 'n' defb 076h ;0367 'v' defb 061h ;0368 'a' defb 06ch ;0369 'l' defb 069h ;036a 'i' defb 064h ;036b 'd' defb 020h ;036c ' ' defb 053h ;036d 'S' defb 079h ;036e 'y' defb 073h ;036f 's' defb 074h ;0370 't' defb 065h ;0371 'e' defb 06dh ;0372 'm' defb 020h ;0373 ' ' defb 044h ;0374 'D' defb 069h ;0375 'i' defb 073h ;0376 's' defb 06bh ;0377 'k' defb 020h ;0378 ' ' defb 069h ;0379 'i' defb 06eh ;037a 'n' defb 020h ;037b ' ' defb 044h ;037c 'D' defb 072h ;037d 'r' defb 069h ;037e 'i' defb 076h ;037f 'v' defb 065h ;0380 'e' defb 020h ;0381 ' ' INVALID_end: pop hl ;0382 Restore HL register (display parameters) pop bc ;0383 Restore BC register (error code and return address) ld de,0008h ;0384 DE = 8 (offset for drive number display) add hl,de ;0387 HL += 8 (position for drive number) add hl,de ;0388 HL += 8 again (total offset = 16) inc hl ;0389 HL += 1 (final position for drive character) ld a,004h ;038a Memory bank 4 (display memory access) out (0c8h),a ;038c Select display memory bank ld (hl),b ;038e Store drive number/character in display xor a ;038f Clear A (bank 0) out (0c8h),a ;0390 Restore normal memory mapping call delayloop ;0392 Wait for user to see error message call delayloop ;0395 Additional delay call setupclearscreen2 ;0398 Clear screen and prepare for retry call readydisk ;039b Display "Ready For System Disk" again exx ;039e Switch to alternate register set pop bc ;039f Restore registers from stack scf ;03a0 Set carry flag (error condition) ret ;03a1 Return to caller ; ================================================================================ ; BOOT SECTOR VALIDATION ROUTINE ; ================================================================================ ; Validates boot sector contents and determines next actions ; Input: Boot sector loaded at 0x4000 ; Output: Carry set if invalid, Z flag indicates additional reads needed sub_03a2h: ld a,003h ;03a2 Set boot status = 3 (validation in progress) ld (0ff8bh),a ;03a4 Store at boot status location ld hl,0401dh ;03a7 Point to boot sector validation byte ld a,(hl) ;03aa Load validation byte cp 0e5h ;03ab Check for 0xE5 (invalid marker 1) scf ;03ad Set carry flag (error) ret z ;03ae Return if invalid (0xE5) cp 06ch ;03af Check for 0x6C (invalid marker 2) scf ;03b1 Set carry flag (error) ret z ;03b2 Return if invalid (0x6C) add a,001h ;03b3 Add 1 to validation byte jr nc,l03bdh ;03b5 If no carry, continue validation ld hl,0ff8bh ;03b7 Point to boot status ld (hl),002h ;03ba Set status = 2 (special boot mode) ret ;03bc Return with status 2 l03bdh: inc hl ;03bd Move to next boot sector parameter ld b,(hl) ;03be Get parameter 1 ld a,b ;03bf Copy to A inc hl ;03c0 Move to next parameter ld c,(hl) ;03c1 Get parameter 2 add a,001h ;03c2 Add 1 to parameter 1 adc a,c ;03c4 Add parameter 2 with carry ld hl,0ff8bh ;03c5 Point to boot status ld (hl),002h ;03c8 Set status = 2 (default) jr z,l03d4h ;03ca If sum is zero, continue ld (hl),001h ;03cc Set status = 1 (normal boot) ld a,b ;03ce Get parameter 1 again or c ;03cf OR with parameter 2 scf ;03d0 Set carry flag (error) ret z ;03d1 Return with error if both parameters are zero or a ;03d2 Clear carry flag (success) ret ;03d3 Return with success l03d4h: ld bc,0001h ;03d4 BC = 1 (additional sector needed) or a ;03d7 Clear carry flag (success, additional read needed) ret ;03d8 Return indicating additional sector read required ; ================================================================================ ; "READY FOR SYSTEM DISK" MESSAGE DISPLAY ; ================================================================================ ; Displays the ready message showing ROM version readydisk: ld de,displaymem ;03d9 DE = display memory base address rst 10h ;03dc RST 10h: Display message routine ; ================================================================================ ; "READY FOR SYSTEM DISK" MESSAGE DATA ; ================================================================================ ; BLOCK 'READY' (start 0x03dd end 0x03fb) READY_start: defb 01dh ;03dd Message length: 29 characters defb 052h ;03de 'R' - "R3-00C Ready For System Disk " defb 033h ;03df '3' defb 02dh ;03e0 '-' defb 030h ;03e1 '0' defb 030h ;03e2 '0' defb 043h ;03e3 'C' defb 020h ;03e4 ' ' defb 052h ;03e5 'R' defb 065h ;03e6 'e' defb 061h ;03e7 'a' defb 064h ;03e8 'd' defb 079h ;03e9 'y' defb 020h ;03ea ' ' defb 046h ;03eb 'F' defb 06fh ;03ec 'o' defb 072h ;03ed 'r' defb 020h ;03ee ' ' defb 053h ;03ef 'S' defb 079h ;03f0 'y' defb 073h ;03f1 's' defb 074h ;03f2 't' defb 065h ;03f3 'e' defb 06dh ;03f4 'm' defb 020h ;03f5 ' ' defb 044h ;03f6 'D' defb 069h ;03f7 'i' defb 073h ;03f8 's' defb 06bh ;03f9 'k' defb 020h ;03fa ' ' READY_end: call delayloop ;03fb Wait briefly after displaying message ret ;03fe Return to caller ; ================================================================================ ; INTERNAL DELAY ROUTINE (PART OF READY FUNCTION) ; ================================================================================ ; This is part of the ready function flow, not a standalone delay routine ld b,00ah ;03ff B = 10 (outer loop counter) ld hl,0000h ;0401 HL = 0 (inner loop counter) l0404h: inc hl ;0404 Increment HL ld a,l ;0405 Test if HL reached 0x0000 again or h ;0406 (after wrapping around 65536 times) jr nz,l0404h ;0407 Continue inner loop until HL wraps to 0 djnz l0404h ;0409 Decrement B and repeat outer loop jp memcmp ;040b Jump to memory compare routine ; ================================================================================ ; DISK SECTOR READ ROUTINES ; ================================================================================ ; Main disk I/O routines for reading boot sectors and program data sub_040eh: ld de,00100h ;040e DE = 0x0100 (256 bytes = 1 sector) ld hl,04000h ;0411 HL = 0x4000 (sector buffer address) sub_0414h: push bc ;0414 Save BC (track/sector parameters) push ix ;0415 Save IX pop bc ;0417 BC = IX (return address) ld a,c ;0418 Get low byte of return address pop bc ;0419 Restore original BC cp 010h ;041a Check if return address low byte < 0x10 jp nc,l06c1h ;041c If >= 0x10, jump to alternate routine l041fh: ld a,005h ;041f A = 5 (retry counter for disk operations) l0421h: ex af,af' ;0421 Save retry counter in AF' push bc ;0422 Save BC (track/sector) ex (sp),hl ;0423 Exchange HL with top of stack ld a,l ;0424 Get low byte and 00fh ;0425 Mask to lower 4 bits push bc ;0427 Save BC again push af ;0428 Save masked value ld a,(0ff81h) ;0429 Get disk parameter flag and a ;042c Test if zero ld b,000h ;042d B = 0 (default sector offset) jr z,l0433h ;042f If flag is zero, use offset 0 ld b,010h ;0431 B = 0x10 (alternate sector offset) l0433h: pop af ;0433 Restore masked value from stack add a,b ;0434 Add sector offset (0 or 0x10) inc a ;0435 Add 1 (sectors are 1-based) out (0b2h),a ;0436 Write to floppy sector register add hl,hl ;0438 HL *= 2 (shift left) add hl,hl ;0439 HL *= 2 (shift left again) add hl,hl ;043a HL *= 2 (shift left again) add hl,hl ;043b HL *= 2 (total: HL *= 16 for track calculation) cp 011h ;043c Compare sector with 17 ld a,h ;043e Get high byte (track number) out (0b3h),a ;043f Write to floppy track register jr c,l0453h ;0441 If sector < 17, skip extended handling rra ;0443 Rotate right (divide by 2) out (0b3h),a ;0444 Write modified track to floppy register push ix ;0446 Save IX pop bc ;0448 BC = IX ld a,b ;0449 Get high byte of IX jr nc,l044eh ;044a If no carry from rotate, skip or 010h ;044c Set bit 4 (extended track flag) l044eh: ld (0ff82h),a ;044e Store drive control byte out (0c0h),a ;0451 Write to floppy drive control register l0453h: pop bc ;0453 Restore BC (track/sector parameters) pop hl ;0454 Restore HL (buffer address) ld a,01dh ;0455 Floppy command 0x1D (read sector with retry) call setfloppystatus ;0457 Execute floppy command and wait for completion and 098h ;045a Check error bits: bit 7=not ready, 4=CRC error, 3=lost data jr nz,l0486h ;045c If any error bits set, handle error call sub_04c1h ;045e Setup DMA transfer parameters ; Multi-sector read loop l0461h: ld a,(0ff82h) ;0461 Get drive control byte bit 4,a ;0464 Test bit 4 (extended track flag) ld a,082h ;0466 Floppy command 0x82 (read data) jr z,l046ch ;0468 If bit 4 clear, use standard command ld a,08ah ;046a Floppy command 0x8A (read data - extended) l046ch: call setfloppystatus ;046c Execute read command and wait and 09ch ;046f Check error bits: bit 7=not ready, 4=CRC, 3=lost data, 2=record not found jr nz,l0486h ;0471 If any error, handle it inc h ;0473 Increment buffer high byte (next page) inc bc ;0474 Increment sector count dec d ;0475 Decrement remaining sector count ret z ;0476 Return if all sectors read (D=0) ld a,c ;0477 Get current sector number and 00fh ;0478 Mask to lower 4 bits (sectors 0-15) jr z,l041fh ;047a If wrapped to 0, start new track in a,(0b2h) ;047c Read current sector register inc a ;047e Increment to next sector out (0b2h),a ;047f Write back to sector register ld a,005h ;0481 Reset retry counter to 5 l0483h: ex af,af' ;0483 Save retry counter jr l0461h ;0484 Continue reading next sector ; Error handling for disk read operations l0486h: scf ;0486 Set carry flag (error) bit 7,a ;0487 Test bit 7 (drive not ready) ret nz ;0489 Return immediately if drive not ready ex af,af' ;048a Get retry counter dec a ;048b Decrement retry count jr nz,l0421h ;048c If retries left, try again ex af,af' ;048e Restore error status bit 4,a ;048f Test bit 4 (CRC error) jr z,l049fh ;0491 If not CRC error, return failure ld a,(0ff81h) ;0493 Get disk parameter flag and a ;0496 Test if zero jr nz,l049fh ;0497 If non-zero, return failure cpl ;0499 Complement (0x00 -> 0xFF) ld (0ff81h),a ;049a Store inverted flag (try alternate sectors) jr l041fh ;049d Retry with alternate sector numbering l049fh: scf ;049f Set carry flag (permanent error) ret ;04a0 Return with error ; ================================================================================ ; DISK INITIALIZATION AND SEEK ROUTINE ; ================================================================================ ; Initialize floppy controller and seek to track 0 sub_04a1h: push bc ;04a1 Save BC register push ix ;04a2 Save IX register pop bc ;04a4 BC = IX (return address) ld a,c ;04a5 Get low byte of return address pop bc ;04a6 Restore original BC cp 010h ;04a7 Check if return address low byte < 0x10 jp nc,l0788h ;04a9 If >= 0x10, jump to alternate routine ld a,001h ;04ac Floppy command 0x01 (restore/recalibrate to track 0) call setfloppystatus ;04ae Execute restore command and 004h ;04b1 Check bit 2 (seek error/track 0 not found) ret nz ;04b3 Return with error if seek failed scf ;04b4 Set carry flag (error - unexpected!) ret ;04b5 Return with error ; ================================================================================ ; FLOPPY CONTROLLER COMMAND EXECUTION ; ================================================================================ ; Sends command to floppy controller and waits for completion ; Input: A = floppy command ; Output: A = final status register setfloppystatus: out (0b0h),a ;04b6 Write command to floppy controller ; Wait for controller ready (INTRQ signal) l04b8h: in a,(0b4h) ;04b8 Read PIO A data register bit 4,a ;04ba Test bit 4 (floppy controller INTRQ signal) jr z,l04b8h ;04bc Wait until INTRQ goes high (command complete) in a,(0b0h) ;04be Read final status from floppy controller ret ;04c0 Return with status in A ; ================================================================================ ; DMA SETUP ROUTINES ; ================================================================================ ; Configure Z80 DMA controller for floppy disk data transfers sub_04c1h: push bc ;04c1 Save BC register ld bc,0b301h ;04c2 B=0xB3 (DMA port), C=0x01 (DMA command) jr l04cbh ;04c5 Jump to common DMA setup sub_04c7h: push bc ;04c7 Save BC register ld bc,07803h ;04c8 B=0x78 (different setting), C=0x03 (DMA command) l04cbh: ld a,b ;04cb Get DMA parameter ld (0ff8ch),a ;04cc Store DMA configuration ld a,c ;04cf Get DMA command out (0b4h),a ;04d0 Write to PIO A data register (DMA control) ld bc,006ach ;04d2 B=6 (loop counter), C=0xAC (DMA port) ld a,0c3h ;04d5 DMA reset command l04d7h: out (c),a ;04d7 Send reset command to DMA controller djnz l04d7h ;04d9 Repeat 6 times (ensure DMA is reset) ld a,07dh ;04db DMA disable command out (c),a ;04dd Send disable to DMA controller out (c),l ;04df Send L register to DMA (low address byte) out (c),h ;04e1 Send H register to DMA (high address byte) out (c),e ;04e3 Send E register to DMA (low count byte) out (c),d ;04e5 Send D register to DMA (high count byte) push hl ;04e7 Save HL register ld hl,004fbh ;04e8 Point to DMA parameter table ld b,003h ;04eb Send 3 bytes otir ;04ed Output 3 bytes from (HL) to port C ld a,(0ff8ch) ;04ef Get stored DMA configuration out (c),a ;04f2 Send to DMA controller ld b,005h ;04f4 Send 5 more bytes otir ;04f6 Output 5 bytes from (HL) to port C pop hl ;04f8 Restore HL register pop bc ;04f9 Restore BC register ret ;04fa Return ; DMA parameter table inc d ;04fb DMA parameter byte 1 jr z,l0483h ;04fc DMA parameter bytes 2-3 adc a,d ;04fe DMA parameter byte 4 rst 8 ;04ff DMA parameter byte 5 (restart vector) ld bc,087cfh ;0500 DMA parameter bytes 6-7-8 ; ================================================================================ ; SCREEN SETUP AND CLEAR ROUTINES ; ================================================================================ ; Initialize CRT controller and clear display memory setupclearscreen2: pop ix ;0503 Get return address from stack setupclearscreen: ; Entry point during initialization with IX=0x0092 xor a ;0505 A = 0 (starting register number) ld bc,00eb9h ;0506 C=0xB9 (CRT data port), B=14 (register count) ld hl,0054fh ;0509 Point to CRT register table setupclearloop: out (0b8h),a ;050c Write register number to CRT register select inc a ;050e Increment to next register number outi ;050f Output (HL) to port C, increment HL, decrement B jr nz,setupclearloop ;0511 Loop until B=0 (all 14 registers written) ld de,03002h ;0513 DE = display memory + 2 (destination) ld hl,displaymem ;0516 HL = display memory base (source) ld bc,00ffeh ;0519 BC = 4094 bytes (2K display memory - 2) ; RST 08 jumps here with different parameters: HL=300C, DE=300E, BC=004E, IX=032F l051ch: ld a,004h ;051c Memory bank 4 (display memory) out (0c8h),a ;051e Select display memory bank xor a ;0520 A = 0 (clear character) ld (hl),a ;0521 Store 0x00 at display memory (character) inc hl ;0522 Move to attribute byte ld (hl),020h ;0523 Store 0x20 (space character attribute) dec hl ;0525 Go back to character position ldir ;0526 Copy pattern throughout display memory xor a ;0528 A = 0 (normal memory bank) out (0c8h),a ;0529 Restore normal memory mapping jp (ix) ;052b Continue execution at IX ; ================================================================================ ; CLEAR TOP LINE ROUTINE ; ================================================================================ ; Clears a single line (80 characters) at the specified address cleartopline: push de ;052d Save original DE ld l,e ;052e HL = DE (copy destination address) ld h,d ;052f inc de ;0530 DE += 2 (destination for copy) inc de ;0531 ld bc,0004eh ;0532 BC = 78 words (80 chars - 2 = 78 more chars) push ix ;0535 Save original IX ld ix,clearlineend ;0537 Set return address to 0x053D jr l051ch ;053b Jump to screen clear routine ; Screen clear routine returns here clearlineend: pop ix ;053d Restore original IX pop de ;053f Restore original DE ret ;0540 Return to caller ; ================================================================================ ; TEXT DISPLAY ROUTINE ; ================================================================================ ; Displays text messages on screen using character/attribute pairs ; Input: BC = character count, HL = message source, DE = screen target printroutine: ld a,004h ;0541 Memory bank 4 (display memory) out (0c8h),a ;0543 Select display memory bank printcharloop: inc de ;0545 Skip to attribute byte (every other address) ldi ;0546 Copy (HL) to (DE), increment both, decrement BC jp pe,printcharloop ;0548 Continue while BC ≠ 0 (parity even = BC not zero) xor a ;054b A = 0 (normal memory bank) out (0c8h),a ;054c Restore normal memory mapping jp (hl) ;054e Jump to address in HL ; ================================================================================ ; CRT CONTROLLER REGISTER TABLE (6845 CRTC) ; ================================================================================ ; 14-byte table of values for CRT controller registers R0-R13 CRT_REGISTER_TABLE: defb 069h ;054f R0: Horizontal Total = 105 characters defb 050h ;0550 R1: Horizontal Displayed = 80 characters defb 056h ;0551 R2: Horizontal Sync Position = 86 defb 00bh ;0552 R3: Horizontal Sync Width = 11 defb 019h ;0553 R4: Vertical Total = 25 rows defb 003h ;0554 R5: Vertical Total Adjust = 3 defb 018h ;0555 R6: Vertical Displayed = 24 rows defb 018h ;0556 R7: Vertical Sync Position = 24 defb 000h ;0557 R8: Interlace Mode = 0 (non-interlaced) defb 00bh ;0558 R9: Maximum Scan Line = 11 (12 lines per char) defb 020h ;0559 R10: Cursor Start = 32 (cursor off) defb 000h ;055a R11: Cursor End = 0 defb 000h ;055b R12: Start Address High = 0 defb 000h ;055c R13: Start Address Low = 0 CRT_TABLE_END: ; ================================================================================ ; ADVANCED SCREEN CLEAR ROUTINES ; ================================================================================ pop hl ;055d Restore HL register jr l0562h ;055e Jump to screen clear loop screenclearloop: otir ;0560 Output B bytes from (HL) to port C l0562h: ld c,(hl) ;0562 Get I/O port number from table inc hl ;0563 Move to count byte ld b,(hl) ;0564 Get byte count inc hl ;0565 Move to data ld a,b ;0566 Test count and a ;0567 Check if zero jr nz,screenclearloop ;0568 If not zero, output data block jp (hl) ;056a Jump to next routine screenclearnetry2: ld de,03100h ;056b DE = 0x3100 (display line 1 start address) ld a,00fh ;056e CRT register 15 (cursor position low byte) out (0b8h),a ;0570 Select CRT register 15 xor a ;0572 A = 0 (cursor position = 0) out (0b9h),a ;0573 Write cursor position to CRT in a,(0bbh) ;0575 Read from port 0xBB (keyboard status?) or a ;0577 Test status ret nz ;0578 Return if non-zero (key pressed?) ld de,030a0h ;0579 DE = 0x30A0 (alternate display position) ret ;057c Return ; ================================================================================ ; DELAY LOOP ROUTINE ; ================================================================================ ; Provides more precise timing delays using stack manipulation delayloop: ld hl,04600h ;057d HL = 17920 (delay counter) l0580h: dec hl ;0580 Decrement counter ex (sp),hl ;0581 Exchange HL with top of stack (add delay) ex (sp),hl ;0582 Exchange back (more delay) ex (sp),hl ;0583 Exchange again (even more delay) ex (sp),hl ;0584 Exchange back (maximum delay per loop) ld a,l ;0585 Test if HL reached zero or h ;0586 jr nz,l0580h ;0587 Continue loop until HL = 0 ret ;0589 Return after ~17920 * 4 clock cycles pop ix ;058a Clean up stack (dead code?) ; ================================================================================ ; CRT CONTROLLER INITIALIZATION ; ================================================================================ ; Complete CRT setup with buzzer control and I/O initialization setupcrt: ld a,00fh ;058c CRT register 15 (cursor position low) out (0b8h),a ;058e Select CRT register 15 xor a ;0590 A = 0 (cursor off) out (0b9h),a ;0591 Write to CRT data register in a,(0bbh) ;0593 Read keyboard/system status and a ;0595 Test status jr nz,l059ch ;0596 If non-zero, skip buzzer ld a,081h ;0598 Buzzer control byte out (0d4h),a ;059a Turn on buzzer/sound l059ch: ld bc,006cch ;059c B=6 bytes, C=0xCC (I/O port for system control) ld hl,005b8h ;059f Point to I/O initialization table otir ;05a2 Output 6 bytes to port 0xCC (system setup) ld bc,0000h ;05a4 BC = 0 (delay counter) ; Delay loop for system settling l05a7h: ex (sp),hl ;05a7 Exchange HL with stack top (timing delay) ex (sp),hl ;05a8 Exchange back (more timing delay) dec bc ;05a9 Decrement delay counter ld a,b ;05aa Test if BC reached zero or c ;05ab jr nz,l05a7h ;05ac Continue delay loop ld a,080h ;05ae Buzzer off command out (0d4h),a ;05b0 Turn off buzzer ld a,09fh ;05b2 System control value out (0cch),a ;05b4 Final system control setup jp (ix) ;05b6 Continue execution at IX ; ================================================================================ ; I/O INITIALIZATION TABLE ; ================================================================================ ; 6-byte table for system controller setup (port 0xCC) IO_SETUP_TABLE: defb 08eh ;05b8 I/O setup byte 1 (adc a,(hl) opcode) defb 004h ;05b9 I/O setup byte 2 (inc b opcode) defb 092h ;05ba I/O setup byte 3 (sub d opcode) defb 0bfh ;05bb I/O setup byte 4 (cp a opcode) defb 0dfh ;05bc I/O setup byte 5 (rst 18h opcode) defb 0ffh ;05bd I/O setup byte 6 (rst 38h opcode) ; ================================================================================ ; MEMORY COPY ROUTINE WITH BANKING ; ================================================================================ ; Copies data using banked memory (used during boot program loading) l05beh: ld a,001h ;05be Memory bank 1 out (0c8h),a ;05c0 Select bank 1 for memory operations l05c2h: ex af,af' ;05c2 Save AF in alternate register adc a,(hl) ;05c3 Load byte from source (HL) ex af,af' ;05c4 Restore AF inc hl ;05c5 Increment source pointer dec de ;05c6 Decrement byte counter ld a,e ;05c7 Test if DE reached zero or d ;05c8 jr nz,l05c2h ;05c9 Continue copy loop if more bytes out (0c8h),a ;05cb A=0, restore normal memory bank jp l02ech ;05cd Jump back to boot execution routine ; ; ANALYSIS OF ALTERNATIVE BOOT PATH (0x05D0-0x0616): ; ================================================== ; ; This represents a remarkable discovery of the Monroe OC8820's dual-OS boot capability. ; The system implements support for two operating systems through calculated ; indirect jumps, creating a sophisticated OS-selection boot system. ; ; OPERATING SYSTEM BOOT MODES: ; ---------------------------- ; Mode 0/1: Standard boot path - Monroe OS8 (Monroe's proprietary operating system) ; Mode 2: CP/M boot path - Industry standard OS for business applications ; Mode 2+: Advanced Monroe OS8 features and configurations ; ; DUAL-OS ENTRY MECHANISM: ; ------------------------ ; 1. Boot disk contains OS identification in banked memory (0xFF80-0xFF92 range) ; 2. Main boot code reads OS type and calculates appropriate boot vector ; 3. Address calculation: Base(4) + OS_Parameter + AdvancedFeatures = OS_BootVector ; 4. Target address stored in IX via push BC/pop IX mechanism ; 5. Later jp (ix) instruction jumps to OS-specific initialization code ; ; OS CONFIGURATION DATA STRUCTURE (in banked memory): ; -------------------------------------------------- ; 0xFF80: Base OS configuration flag (combined with runtime parameters) ; 0xFF81: OS-specific configuration byte (CP/M BIOS params or Monroe OS8 settings) ; 0xFF8D: 4-byte OS parameter block #1 (disk geometry, memory layout) ; 0xFF8F: OS validation signature (0x95 = validated Monroe OS8 disk with advanced features) ; 0xFF91: OS boot data byte (entry points, system calls) ; 0xFF92: OS boot data byte (additional OS parameters) ; ; CP/M vs MONROE OS8 BOOT DIFFERENTIATION: ; ---------------------------------------- ; - If mode ≠ 2: Monroe OS8 boot (standard proprietary OS) ; - If mode = 2 and parameter < 16: CP/M boot (industry standard) ; - If mode = 2 and parameter ≥ 16: Check for Monroe OS8 advanced features ; - If signature = 0x95: Monroe OS8 with advanced features (+1 offset) ; - Final jump target = 4 + (OS_parameter-16) + advanced_features_bonus ; ; The final jp (iy) transfers control to the selected OS kernel! ; ;; ================================================================================ ; Entry point: 0x05D0 (reached via jp (ix) with calculated address from 0x05F2-0x05F3) ; This represents a sophisticated secondary boot path for handling different system configurations ; ; Entry conditions: ; - A register contains boot mode indicator ; - C register contains configuration parameter ; - System expects specific memory layout in banked memory l05d0h: cp 002h ;05d0 Compare A with 2 (OS boot mode check: 2 = CP/M selection) ld a,001h ;05d2 Load memory bank 1 selector out (0c8h),a ;05d4 Switch to memory bank 1 for OS-specific operations jr nz,l05f5h ;05d6 If A≠2, use Monroe OS8 (native OS), skip CP/M setup ; CP/M specific initialization (A was equal to 2) ld a,(0ff81h) ;05d8 Load CP/M configuration byte from boot disk ld (0022h),a ;05db Store CP/M config in system variable (BIOS parameters) ld a,c ;05de Get CP/M parameter from C register sub 010h ;05df Subtract 16 (check if parameter >= 16 for advanced CP/M) jr c,l05f5h ;05e1 If C<16, use basic CP/M boot, jump to common path ld c,a ;05e3 Update C with adjusted value (C = C-16) jr z,l05eeh ;05e4 If result is zero (C was exactly 16), basic advanced CP/M ; Advanced Monroe OS8 features when booting from CP/M mode ld a,(0ff8fh) ;05e6 Load validation signature from boot disk cp 095h ;05e9 Compare with Monroe OS8 advanced feature signature 0x95 jr nz,l05eeh ;05eb If not Monroe OS8 signature, use standard CP/M boot inc c ;05ed Valid Monroe OS8 features: increment C (Monroe-specific CP/M extensions) l05eeh: ; Calculate OS-specific jump target address ld a,004h ;05ee Base offset = 4 add a,c ;05f0 Add OS-derived offset to base ld c,a ;05f1 C now contains calculated OS boot vector offset push bc ;05f2 Push BC to stack pop ix ;05f3 Pop into IX - now IX = OS boot vector (B×256 + OS_offset) ; This creates the target address for OS-specific initialization l05f5h: ; Common path for both operating systems (Monroe OS8 and CP/M) ; OS-specific data preparation and parameter setup ld a,(0ff80h) ;05f5 Load base OS configuration from boot disk or c ;05f8 Combine with OS-specific offset parameter ld c,a ;05f9 Store combined OS configuration ld a,(0ff91h) ;05fa Load OS boot parameter 1 from disk (entry points, BIOS vectors) ld (de),a ;05fd Store to OS parameter area (DE points to system area) inc de ;05fe Advance destination pointer ; Copy 4-byte OS parameter block from boot disk push bc ;05ff Save BC (OS configuration) ld bc,00004h ;0600 Set count = 4 bytes ldir ;0603 Copy 4 bytes: Monroe OS8 or CP/M system parameters ; Set up for second OS parameter block copy ld de,00023h ;0605 DE = destination address 0x0023 (OS parameter area) ld hl,0ff8dh ;0608 HL = source in banked memory 0xFF8D (OS data block 2) ld a,(0ff92h) ;060b Load OS boot parameter 2 (system vectors, disk geometry) ld (de),a ;060e Store at 0x0023 inc de ;060f DE = 0x0024 ; Copy second 4-byte OS parameter block ld bc,00004h ;0610 Set count = 4 bytes ldir ;0613 Copy 4 bytes: Monroe OS8 system tables or CP/M BIOS tables pop bc ;0615 Restore BC (OS configuration) jp (iy) ;0616 Jump to selected OS kernel entry point! (Monroe OS8 or CP/M) ; ================================================================================ ; DATA TABLE AND DISK CONTROLLER INITIALIZATION ; ================================================================================ defb 005h ;0618 Controller parameter 1 defb 080h ;0619 Controller parameter 2 (0x80 = enable flag?) defb 005h ;061a Controller parameter 3 defb 000h ;061b Controller parameter 4 (terminator?) ; ================================================================================ ; DISK CONTROLLER SETUP AND STATUS CHECK ROUTINE ; ================================================================================ ; Initializes the disk controller and waits for ready status ; Uses the 4-byte parameter table above (0x0618-0x061B) ; Returns: Carry set if timeout/error, clear if success sub_061ch: ld bc,002a3h ;061c B=2 bytes, C=0xA3 (port number for disk controller) ld hl,00618h ;061f HL points to controller parameter table above otir ;0622 Output 2 bytes from (HL) to port 0xA3, auto-increment HL ld b,0ffh ;0624 B = 255 (timeout counter for controller ready) l0626h: ; Wait for disk controller ready status in a,(079h) ;0626 Read disk controller status port cp 0c7h ;0628 Compare with ready status value 0xC7 jr z,l0630h ;062a If ready (0xC7), continue with operation djnz l0626h ;062c Decrement timeout counter, loop if not expired scf ;062e Set carry flag (timeout error) ret ;062f Return with error l0630h: ; Controller is ready - execute read operation call reading ;0630 Execute disk read command ret c ;0633 Return if read error occurred ; Analyze controller response for configuration in a,(0ffh) ;0634 Read controller configuration register rra ;0636 Rotate right (check bit 0) rra ;0637 Rotate right again (check bit 1) and 007h ;0638 Mask to get lower 3 bits (configuration value 0-7) ; *** BOOT DEVICE SELECTION LOGIC *** ; Configuration value determines boot device priority: ; 0 = Default (floppy-only system) ; 1 = Hard disk + floppy system (hard disk priority) ; 2+ = Advanced hard disk system (hard disk with extended features) ld hl,007e2h ;063a Default: point to floppy-only configuration table jr z,l064fh ;063d If value=0, use floppy-only mode, skip device selection ld hl,007d6h ;063f Point to hard disk + floppy configuration table dec a ;0642 Decrement configuration value jr z,l0648h ;0643 If value was 1, use hard disk + floppy mode ld hl,007cah ;0645 Point to advanced hard disk configuration (value ≥ 2) l0648h: call sub_076bh ;0648 Execute configuration-specific routine call reading ;064b Execute another disk read ret c ;064e Return if error l064fh: ; Copy configuration data to system memory ld de,0ff8dh ;064f DE = destination in banked memory (system parameters) ld bc,00004h ;0652 BC = 4 bytes to copy ldir ;0655 Copy 4 bytes from (HL) to system memory jp l077fh ;0657 Jump to next stage of disk initialization ; ================================================================================ ; DISK COMMAND EXECUTION ROUTINE ; ================================================================================ ; Executes specific floppy disk commands (0x10, 0x11) used during boot sequence ; This routine handles low-level disk operations like recalibrate and seek ; Input: C = disk command (0x10 = recalibrate, 0x11 = seek/position) ; Output: Carry flag set if error, clear if success sub_065ah: push bc ;065a Save BC register pop ix ;065b IX = BC (save original command for later use) ld a,010h ;065d A = 0x10 (base command value) sub c ;065f A = 0x10 - C (calculate command offset) jr z,l0664h ;0660 If C=0x10 (recalibrate), use A=0 parameter ld a,020h ;0662 A = 0x20 (seek command parameter) l0664h: ; Build disk command parameter block ld hl,0ff83h ;0664 Point to disk parameter buffer in banked memory ld b,004h ;0667 B = 4 (number of parameters to set) ld (hl),008h ;0669 Store 0x08 (command type/drive select) inc hl ;066b Move to next parameter slot ld (hl),a ;066c Store command-specific parameter (0x00 or 0x20) l066dh: ; Clear remaining parameters inc hl ;066d Move to next parameter slot ld (hl),000h ;066e Clear parameter (set to 0x00) djnz l066dh ;0670 Clear remaining 3 parameters (total 6 bytes) ; Execute the disk command call reading ;0672 Execute the prepared disk command ret c ;0675 Return immediately if command failed call moveoutreseta ;0676 Move/output result data call reading2 ;0679 Read final status and 002h ;067c Check bit 1 (error flag) ret z ;067e Return success if bit 1 clear scf ;067f Set carry flag (error) ret ;0680 Return with error ; ================================================================================ ; CRITICAL DISK ERROR HANDLER ; ================================================================================ ; Handles severe disk system errors that prevent successful boot ; This is called when disk controller hardware fails or becomes unresponsive ; Displays Error #1 message and enters service mode print_error1: push bc ;0681 Save BC register state call screenclearnetry2 ;0682 Clear screen and setup error display rst 10h ;0685 RST 10h: Display error message (points to message below) ; ================================================================================ ; ERROR #1 MESSAGE DATA - CRITICAL DISK SYSTEM ERROR ; ================================================================================ ; "Error 1: Disk system error, Call Service" - 40 characters ; This indicates hardware-level disk controller failure requiring service ERROR1_start: defb 028h ;0686 Message length: 40 characters defb 045h ;0687 'E' defb 072h ;0688 'r' defb 072h ;0689 'r' defb 06fh ;068a 'o' defb 072h ;068b 'r' defb 020h ;068c ' ' defb 031h ;068d '1' defb 03ah ;068e ':' defb 020h ;068f ' ' defb 044h ;0690 'D' defb 069h ;0691 'i' defb 073h ;0692 's' defb 06bh ;0693 'k' defb 020h ;0694 ' ' defb 073h ;0695 's' defb 079h ;0696 'y' defb 073h ;0697 's' defb 074h ;0698 't' defb 065h ;0699 'e' defb 06dh ;069a 'm' defb 020h ;069b ' ' defb 065h ;069c 'e' defb 072h ;069d 'r' defb 072h ;069e 'r' defb 06fh ;069f 'o' defb 072h ;06a0 'r' defb 02ch ;06a1 ',' defb 020h ;06a2 ' ' defb 043h ;06a3 'C' defb 061h ;06a4 'a' defb 06ch ;06a5 'l' defb 06ch ;06a6 'l' defb 020h ;06a7 ' ' defb 053h ;06a8 'S' defb 065h ;06a9 'e' defb 072h ;06aa 'r' defb 076h ;06ab 'v' defb 069h ;06ac 'i' defb 063h ;06ad 'c' defb 065h ;06ae 'e' ERROR1_end: ; ================================================================================ ; ERROR RECOVERY AND SYSTEM RESTART ; ================================================================================ ; After displaying the error, system performs cleanup and restart sequence error1_recovery: call delayloop ;06af Delay to allow user to read error message call delayloop ;06b2 Additional delay for visibility call delayloop ;06b5 Final delay before restart attempt call setupclearscreen2 ;06b8 Clear screen and reinitialize display system call readydisk ;06bb Attempt to ready disk system for retry pop bc ;06be Restore BC register from stack scf ;06bf Set carry flag (indicate error condition) ret ;06c0 Return with error status ; ================================================================================ ; DISK SECTOR READ WITH RETRY LOGIC ; ================================================================================ ; Advanced disk read routine with automatic retry and error recovery ; Input: D = sector count, BC = parameters, HL = buffer pointer ; Output: Carry set if unrecoverable error, clear if success l06c1h: call sub_04c7h ;06c1 Setup disk operation parameters ld a,b ;06c4 Get B register (track/cylinder) ld (0ff85h),a ;06c5 Store track parameter in system memory ld a,c ;06c8 Get C register (sector/head) ld (0ff86h),a ;06c9 Store sector parameter in system memory l06cch: ld a,d ;06cc Get D register (sector count) ld (0ff87h),a ;06cd Store sector count parameter push bc ;06d0 Save BC registers (track/sector info) push hl ;06d1 Save HL registers (buffer pointer) call reading ;06d2 Execute disk read command jp c,l06fbh ;06d5 If read error, jump to cleanup and return ; Successful read - transfer parameter data ld hl,0ff83h ;06d8 Point to disk parameter buffer ld bc,00678h ;06db B=6 bytes to transfer, C=0x78 (I/O port for data) l06deh: ; Wait for controller ready and transfer data in a,(079h) ;06de Read disk controller status port and 041h ;06e0 Check bits 6 and 0 (ready and data request flags) jr nz,l06deh ;06e2 Wait until controller indicates ready for transfer outi ;06e4 Transfer byte: output (HL) to port C, increment HL, decrement B jr nz,l06deh ;06e6 Continue until all 6 parameter bytes transferred out (07ah),a ;06e8 Write final control byte to data port 0x7A nop ;06ea Short timing delay for controller l06ebh: ; Wait for final status and complete operation in a,(079h) ;06eb Read disk controller status and 044h ;06ed Check bits 6 and 2 (completion status flags) jr nz,l06ebh ;06ef Wait for completion status change out (07bh),a ;06f1 Write completion status to control port 0x7B call reading2 ;06f3 Read final operation status and 002h ;06f6 Check bit 1 (error indication) call nz,sub_06ffh ;06f8 If error bit set, call error recovery routine l06fbh: ; Cleanup and return pop hl ;06fb Restore HL registers (buffer pointer) pop bc ;06fc Restore BC registers (track/sector) inc bc ;06fd Increment BC to next sector position ret ;06fe Return to caller ; ================================================================================ ; ADVANCED DISK ERROR RECOVERY ROUTINE ; ================================================================================ ; Sophisticated error recovery with retry logic and validation ; Called when initial read fails - attempts recovery and validation ; Returns: Carry set if unrecoverable, clear if recovery successful sub_06ffh: call reading ;06ff Attempt another disk read operation ret c ;0702 Return immediately if read still failing ld a,003h ;0703 A = 3 (retry/recovery command code) call moveout ;0705 Execute move/output operation with retry command ld bc,00478h ;0708 B=4 bytes to read, C=0x78 (I/O data port) ld hl,0ff89h ;070b Point to error recovery buffer in system memory l070eh: ; Read recovery data from controller in a,(079h) ;070e Read disk controller status port cp 00fh ;0710 Compare with 0x0F (ready for data transfer) jr nz,l070eh ;0712 Wait until controller indicates ready (status = 0x0F) ini ;0714 Input byte: read from port C to (HL), increment HL, decrement B jr nz,l070eh ;0716 Continue until all 4 recovery bytes read call reading2 ;0718 Read final status after recovery attempt ld a,(0ff89h) ;071b Get first byte from recovery buffer sub 098h ;071e Compare with expected recovery value 0x98 ret z ;0720 Return success (Z flag) if recovery data matches scf ;0721 Set carry flag (recovery failed) ret ;0722 Return with unrecoverable error status ; ================================================================================ ; LOW-LEVEL DISK CONTROLLER COMMUNICATION ROUTINES ; ================================================================================ ; Core routines for sending commands and reading status from disk controller reading: ; Initiate disk read command with timeout protection in a,(079h) ;0723 Read disk controller status port and 080h ;0725 Check bit 7 (controller ready flag) scf ;0727 Set carry flag (assume error initially) ret z ;0728 Return with error if controller not ready ld a,001h ;0729 A = 1 (start read command) out (079h),a ;072b Send start command to disk controller ld b,0ffh ;072d B = 255 (timeout counter - ~255 loop iterations) l072fh: ; Wait for command completion with timeout in a,(079h) ;072f Read controller status port and 080h ;0731 Check ready bit (bit 7) ret z ;0733 Return success (carry clear) if ready bit cleared djnz l072fh ;0734 Decrement timeout counter and continue waiting scf ;0736 Set carry flag (timeout error) ret ;0737 Return with timeout error reading2: in a,(079h) ;0738 Read disk controller status and 044h ;073a Check bits 6 and 2 (busy/status flags) jr nz,reading2 ;073c Wait until both flags clear in a,(078h) ;073e Read result from data port ld b,a ;0740 Save result in B l0741h: in a,(079h) ;0741 Read controller status again and 042h ;0743 Check bits 6 and 1 (different status bits) jr nz,l0741h ;0745 Wait until these flags clear in a,(078h) ;0747 Read final data byte ld a,b ;0749 Restore original result to A ret ;074a Return with status in A ; ================================================================================ ; DISK COMMAND OUTPUT ROUTINES ; ================================================================================ ; Send command sequences to disk controller moveoutreseta: ld a,000h ;074b A = 0 (reset command) moveout: call sub_0760h ;074d Send A to disk controller ld a,(0ff84h) ;0750 Get stored command parameter call sub_0760h ;0753 Send parameter to controller ld a,000h ;0756 A = 0 (padding/terminator) ld b,004h ;0758 B = 4 (send 4 zero bytes) l075ah: call sub_0760h ;075a Send zero byte to controller djnz l075ah ;075d Repeat 4 times ret ;075f Return ; ================================================================================ ; LOW-LEVEL DISK CONTROLLER I/O ; ================================================================================ ; Fundamental routine for sending bytes to disk controller sub_0760h: push af ;0760 Save byte to send l0761h: in a,(079h) ;0761 Read controller status and 041h ;0763 Check bits 6 and 0 (ready/busy flags) jr nz,l0761h ;0765 Wait until controller ready to receive pop af ;0767 Restore byte to send out (078h),a ;0768 Send byte to controller data port ret ;076a Return ; ================================================================================ ; DISK CONTROLLER DATA TRANSFER ; ================================================================================ ; Transfers data block from controller sub_076bh: ld a,00ch ;076b A = 0x0C (data transfer command) call moveout ;076d Send command to controller ld bc,00878h ;0770 B=8 bytes, C=0x78 (data port) l0773h: in a,(079h) ;0773 Read controller status cp 007h ;0775 Compare with 0x07 (data ready) jr nz,l0773h ;0777 Wait until data ready outi ;0779 Input byte: (HL) ← (C), HL++, B-- jr nz,l0773h ;077b Continue until 8 bytes transferred jr reading2 ;077d Jump to read final status ; ================================================================================ ; DISK ERROR RECOVERY AND ALTERNATE ROUTINES ; ================================================================================ l077fh: ld a,0e4h ;077f A = 0xE4 (error recovery command) call steproutine ;0781 Execute step/recovery routine ret z ;0784 Return if successful jp print_error1 ;0785 Jump to disk error handler l0788h: call reading ;0788 Attempt disk read ret c ;078b Return if error ld a,001h ;078c A = 0x01 (step command) call steproutine ;078e Execute step routine ret z ;0791 Return if successful jr print_error3 ;0792 Jump to alternate error handling ; ================================================================================ ; DISK STEP/SEEK ROUTINE ; ================================================================================ ; Executes disk step commands (seek operations) steproutine: call moveout ;0794 Send step command to controller call reading2 ;0797 Read controller status and 002h ;079a Check bit 1 (error flag) ret ;079c Return with Z flag set if no error ; ================================================================================ ; DISK MALFUNCTION ERROR HANDLER ; ================================================================================ print_error3: call screenclearnetry2 ;079d Clear screen and setup display rst 10h ;07a0 RST 10h: Display error message ; ================================================================================ ; ERROR #3 MESSAGE DATA - DISK MALFUNCTION ; ================================================================================ ; BLOCK 'ERROR3' (start 0x07a1 end 0x07c9) ERROR3_start: defb 027h ;07a1 Message length: 39 characters defb 045h ;07a2 'E' - "Error #3: Disk Malfunction, Call Service" defb 072h ;07a3 'r' defb 072h ;07a4 'r' defb 06fh ;07a5 'o' defb 072h ;07a6 'r' defb 020h ;07a7 ' ' defb 033h ;07a8 '3' defb 03ah ;07a9 ':' defb 020h ;07aa ' ' defb 044h ;07ab 'D' defb 069h ;07ac 'i' defb 073h ;07ad 's' defb 06bh ;07ae 'k' defb 020h ;07af ' ' defb 04dh ;07b0 'M' defb 061h ;07b1 'a' defb 06ch ;07b2 'l' defb 066h ;07b3 'f' defb 075h ;07b4 'u' defb 06eh ;07b5 'n' defb 063h ;07b6 'c' defb 074h ;07b7 't' defb 069h ;07b8 'i' defb 06fh ;07b9 'o' defb 06eh ;07ba 'n' defb 02ch ;07bb ',' defb 020h ;07bc ' ' defb 043h ;07bd 'C' defb 061h ;07be 'a' defb 06ch ;07bf 'l' defb 06ch ;07c0 'l' defb 020h ;07c1 ' ' defb 053h ;07c2 'S' defb 065h ;07c3 'e' defb 072h ;07c4 'r' defb 076h ;07c5 'v' defb 069h ;07c6 'i' defb 063h ;07c7 'c' defb 065h ;07c8 'e' ERROR3_end: halt ;07c9 System halt - requires service intervention ; ================================================================================ ; DATA TABLES AND CONSTANTS ; ================================================================================ ; Various data tables used by system routines l07cah: defb 001h ;07ca Data table entry 1 defb 032h ;07cb Data table entry 2 defb 004h ;07cc Data table entry 3 defb 001h ;07cd Data table entry 4 defb 031h ;07ce Data table entry 5 defb 000h ;07cf Data table entry 6 defb 040h ;07d0 Data byte defb 00bh ;07d1 Data byte defb 006h ;07d2 Data byte defb 000h ;07d3 Data byte defb 095h ;07d4 Data byte defb 0ffh ;07d5 Data byte defb 001h ;07d6 Data byte l07d7h: defb 032h ;07d7 Data byte defb 002h ;07d8 Data byte defb 001h ;07d9 Data byte defb 031h ;07da Data table entry 1 defb 000h ;07db Data table entry 1 defb 040h ;07dc Data table entry 2 defb 00bh ;07dd Data table entry 2 defb 006h ;07de Data byte defb 000h ;07df Data byte defb 04ah ;07e0 Data byte defb 0ffh ;07e1 Data byte l07e2h: defb 000h ;07e2 Data byte 'Q' defb 000h ;07e3 Data byte (NOP padding) defb 04ah ;07e4 Data byte (NOP padding) l07e5h: defb 0ffh ;07e5 Data byte 'J' ; ROM unused space filled with RST 38h (0FFh) - typical EPROM pattern defb 0ffh ;07e6 Unused ROM space defb 0ffh ;07e7 Unused ROM space defb 0ffh ;07e8 Unused ROM space defb 0ffh ;07e9 Unused ROM space defb 0ffh ;07ea Unused ROM space defb 0ffh ;07eb Unused ROM space defb 0ffh ;07ec Unused ROM space defb 0ffh ;07ed Unused ROM space defb 0ffh ;07ee Unused ROM space defb 0ffh ;07ef Unused ROM space defb 0ffh ;07f0 Unused ROM space defb 0ffh ;07f1 Unused ROM space defb 0ffh ;07f2 Unused ROM space defb 0ffh ;07f3 Unused ROM space defb 0ffh ;07f4 Unused ROM space defb 0ffh ;07f5 Unused ROM space defb 0ffh ;07f6 Unused ROM space defb 0ffh ;07f7 Unused ROM space defb 0ffh ;07f8 Unused ROM space defb 0ffh ;07f9 Unused ROM space defb 0ffh ;07fa Unused ROM space defb 0ffh ;07fb Unused ROM space defb 0ffh ;07fc Unused ROM space defb 0ffh ;07fd Unused ROM space defb 0ffh ;07fe Unused ROM space defb 0ffh ;07ff End of 2K ROM - TMS2516 EPROM ; ================================================================================ ; END OF ROM - MONROE OC8820 BOOT ROM R3.00C ; ================================================================================ ; Total ROM size: 2048 bytes (0x0000-0x07FF) ; Boot process complete - system transfers control to OS at 0xFFA6 ; ================================================================================