; z80dasm 1.1.3 ; command line: z80dasm -l -s rom_strings.sym -g 0x0000 -a metric_cpu-s_mc8_v1.2_2716.bin ;############################################################################## ; METRIC 8 COMPUTER SYSTEM ; MONITOR/DEBUGGER REFERENCE MANUAL ;############################################################################## ; ; SYSTEM OVERVIEW: ; The Metric 8 is a sophisticated Z80-based computer system (circa 1980) with ; an advanced monitor/debugger ROM providing comprehensive development tools. ; ; HARDWARE SPECIFICATIONS: ; • CPU: Z80 running at 3.93216MHz (sophisticated timing), crystal at 19.6608MHz ; • ROM: 2 pcs of 2716 EPROM (2KB) containing monitor/debugger ; • RAM: 1KB base workspace + 64KB paged external memory ; • I/O: Z80 DMA controller, NEC µPD765A FDC, sophisticated peripherals ; • Memory Management: Advanced paging system with 8KB windows ; ; MONITOR COMMANDS: ; The monitor provides a '>' prompt and accepts single-letter commands ; followed by hexadecimal parameters. All addresses are 4-digit hex. ; ; MEMORY MODIFICATION COMMANDS: ; ; DEBUGGING/BREAKPOINT COMMANDS: ; • B XXXX - Set execution counter for controlled stepping (Entry: 0x03E2h) ; Sets execution step counter for controlled program stepping/tracing ; XXXX = number of instructions to execute before breaking ; Counter stored at memory location 0x011D0 ; Default count is 1 if no parameter provided (single step) ; Used for single-step debugging and controlled execution ; ; MEMORY COMMANDS: ; • C AAAA BBBB CCCC - Compare memory regions (Entry: 0x0323h) ; Compare memory from AAAA-BBBB with memory starting at CCCC ; Displays differences between the two memory regions ; Silent operation if regions are identical ; ; • D [AAAA] [BBBB] - Display/Examine memory (Entry: 0x0358h) ; D AAAA BBBB: Memory dump display from address AAAA with length BBBB ; D AAAA: Interactive examine/modify starting at address AAAA ; D: Interactive examine/modify from current address ; Interactive mode: Shows one byte, Enter=next, Q=quit, hex=change value ; ; • E [XX] - Examine/modify CPU registers (Entry: 0x0515h) ; E: Display all Z80 registers in formatted list with current values ; Shows: A,B,C,D,E,F,H,L,I,A',B',C',D',E',F',H',L',IX,IY,PC,SP ; E XX: Examine/modify specific register (e.g., "E AF", "E BC", "E HL") ; Output format: "B 0A" (register name, space, 2-digit hex value) ; • F AAAA BBBB DD - Fill memory range with data (Entry: 0x03B7h) ; Fill memory from AAAA to BBBB with byte value DD ; Useful for initializing memory regions ; Fast memory pattern fill operation ; ; • M AAAA BBBB CCCC - Memory move/copy command (Entry: 0x04FCh) ; Copy memory block from AAAA-BBBB to destination starting at CCCC ; Uses LDIR instruction for efficient block transfer ; Handles overlapping regions properly ; ; EXECUTION COMMANDS: ; • G XXXX - Go/Execute program starting from address XXXX (Entry: 0x044Ah) ; Transfers control to user program at specified address ; Restores all CPU registers and begins execution ; Supports breakpoint detection and interrupt handling ; Returns to monitor if breakpoint hit or program exits ; ; • I XXXX - Configure debug display parameters and modes (Entry: 0x03CFh) ; Sets debugging display parameters stored at 0x11D6 ; Used for display width, format, or visualization options ; Special case: "II" jumps to specialized display handler ; ; • J XXXX - Jump/Execute program (alternate Go command) (Entry: 0x0441h) ; Similar functionality to G command - executes program ; Parses hex address and transfers control to user program ; Supports same breakpoint and register restoration features ; ; FILE/DATA TRANSFER COMMANDS: ; • L XXXX - Load Intel HEX records into memory (Entry: 0x089Fh) ; Advanced Intel HEX format loader for program/data transfer ; XXXX parameter specifies base load address (optional, defaults to 0x0000) ; Parses Intel HEX records: ":LLAAAATTDDDDDDCC" format ; LL=byte count, AAAA=address, TT=record type, DD=data, CC=checksum ; Validates checksums and loads data to calculated addresses ; Essential for loading programs from external sources or storage ; Searches for ':' record start markers and processes complete records ; ; SYSTEM DISPLAY COMMANDS: ; • R AAAA BBBB - Read from disk/storage device (Entry: 0x09FFh) ; Read data from disk into memory starting at AAAA with length BBBB ; Uses disk parameters previously configured by O command ; Example: After "O 0 0 5 1", then "R 1000 100" reads 1 sector into 1000h ; Uses floppy disk controller (ports 0xF0, 0xF1, 0xFC) ; Special variant: "RO" redirects to Intel HEX loader (L command) ; ; MEMORY SET AND CALCULATION COMMANDS: ; • S AAAA DD - Set/Store data in memory (Entry: 0x063Fh) ; Store byte value DD at address AAAA, then continue ; Prompts for next address and value in sequence ; Interactive memory loading/initialization command ; ; • N - Next instruction execution/stepping (Entry: 0x049Fh) ; Single-step debugger instruction execution control ; Executes next instruction with debugging support ; Used for step-by-step program analysis and debugging ; ; • H XXXX YYYY - Hex arithmetic calculator (Entry: 0x0887h) ; Performs hex addition and subtraction on values XXXX and YYYY ; Displays both sum (XXXX + YYYY) and difference (XXXX - YYYY) ; Essential for address calculations and memory arithmetic ; Shows results in 4-digit hexadecimal format ; ; • T - Terminal echo/bridge mode (Entry: 0x014Fh) ; Bidirectional serial bridge between ports ; Creates infinite loop transferring data between serial interfaces ; Used for terminal echo, serial bridging, or communication testing ; Must be interrupted to return to monitor ; ; PORT I/O COMMANDS: ; • O D F T S - Floppy disk operation setup command (Entry: 0x09BCh) ; D = Drive number (0-3): Selects physical floppy drive A: through D: ; F = Flags (0-1): Drive control/head selection (0=standard, 1=alternate) ; T = Track (0-76): Track/cylinder number (max 77 tracks for 8" drives) ; S = Sectors (1-26): Sector count per operation (0=seek only, max 27) ; Note: O command only configures disk parameters, not memory addresses ; Examples: "O 0 0 5 1" configures drive A:, track 5, 1 sector ; "O 1 0 0 10" configures drive B:, track 0, 10 sectors ; Special: "OS" boots CP/M operating system from disk ; ; • P XXXX - Port I/O operations (Entry: 0x086Fh) ; Interactive I/O port read/write command ; P XXXX: Read from port XXXX, display value, prompt for new value ; Shows current port value, allows modification ; Special variant: PU goes to upload/checksum utility ; ; DATA TRANSFER COMMANDS: ; • U XXXX YYYY - Upload/Memory checksum utility (Entry: 0x0924h) ; Computes Intel HEX format checksums for memory range XXXX to YYYY ; Displays memory content in Intel HEX record format with checksums ; Essential for creating ROM images and data verification ; Output format: ":LLAAAATT[DD...]CC" where LL=length, AAAA=address, ; TT=type, DD=data bytes, CC=checksum. Handled by l0924h routine. ; ; • W AAAA BBBB - Write to disk/storage device (Entry: 0x09FAh) ; Write data from memory starting at AAAA with length BBBB to disk ; Uses disk parameters previously configured by O command ; Example: After "O 1 0 0 1", then "W 1000 100" writes 1 sector from 1000h ; [Command implementation requires further analysis] ; ; EXTENDED SYSTEM COMMANDS: ; • X - eXecute instruction analysis (Entry: 0x040Fh) ; Instruction analysis and breakpoint management ; Analyzes and executes instructions with debugging support ; Handles breakpoint restoration and instruction stepping ; Provides comprehensive register dump for program analysis ; ; ADDITIONAL COMMANDS: ; • Debug parameters can be configured via additional commands ; • Monitor supports commands: B,C,D,E,F,G,H,I,J,L,M,N,O,P,R,S,T,W,X ; • Use single letters followed by hex parameters as needed ; Values stored at 0x011D6 for various debugging modes ; ; SYSTEM MESSAGES: ; • "BREAK AT XXXX" - Displayed when execution breaks at address XXXX ; System returns to monitor prompt after breakpoints ; ; TECHNICAL FEATURES: ; • Sophisticated hex string parser supporting multi-parameter input ; • Intelligent input processing with space skipping and case conversion ; • Dual-purpose code/data sections for memory efficiency ; • Register state preservation and restoration ; • Interrupt mode 2 support with vector table ; • Advanced memory paging with 64KB external memory card ; • Professional error handling with graceful returns to command prompt ; ; CONTROL CHARACTERS: ; The monitor responds to standard terminal control characters for user control: ; ; • Ctrl+C (0x03 ETX) - Emergency System Reset/Break ; Immediately aborts current operation and returns to monitor ; Resets stack pointer and provides clean restart ; Similar to "break" functionality in modern terminals ; Works during any input operation or command execution ; ; • Ctrl+S (0x13 XOFF) - Pause/Resume Output Flow Control ; Temporarily pauses output display (standard XOFF) ; Press any key to resume output (XON behavior) ; Useful for stopping scrolling during long displays ; Standard terminal flow control implementation ; ; • Backspace (0x08) - Character Deletion During Input ; Deletes previous character from input buffer ; Echoes backspace-space-backspace sequence to terminal ; Provides visual feedback of character removal ; Standard line editing functionality ; ; • DEL (0x7F) - Alternative Character Deletion ; Functions identically to Backspace (0x08) ; Supports both common delete key encodings ; Maintains compatibility with different terminal types ; ; These control characters provide immediate user control over system operation ; and implement standard terminal behavior expected in professional systems. ; ; COMPREHENSIVE MEMORY MAP - Z80 METRIC 8 SYSTEM: ;============================================================================== ; ROM CODE SPACE: ; • 0x0000-0x0FFF: ROM Monitor/Debugger (4KB, 2x 2716 EPROM) ; Contains complete monitor system, command interpreter, ; disk I/O routines, debugging tools, and system initialization ; ; SYSTEM RAM LAYOUT: ; • 0x1000-0x10FF: User workspace (256 bytes) - Available for user programs/data ; • 0x1100-0x11FF: System I/O buffers and communication area (256 bytes) ; - 0x1100: SIO interrupt character buffer (keypress detection) ; - 0x1101-0x1102: Character timing measurement (16-bit, baud rate detection) ; - 0x1104: Console input buffer start (keyboard input processing) ; - 0x1168: Input processing buffer (temporary command storage) ; - 0x1169: Command input buffer (parsed command storage) ; - 0x11CD: Load/transfer address for L command operations ; - 0x11CF: Saved byte backup (breakpoint restoration storage) ; - 0x11D0: Breakpoint/execution counter for debugging ; - 0x11D1: Active breakpoint memory location (current breakpoint address) ; - 0x11D3: Original byte backup (saved from breakpoint location for restoration) ; - 0x11D4: Debug parameters and execution status storage ; - 0x11D6: Debug display parameters and mode settings ; - 0x11D7: Interrupt vector high byte for IM2 mode ; - 0x11D8: Complete register save area (AF,BC,DE,HL,IX,IY,SP) for user program execution ; - 0x11EA: Program execution start address (G/J commands) ; - 0x11EC: User stack pointer backup storage ; - 0x11EE: Saved debug parameters (temporary storage during execution) ; - 0x11F0: Current breakpoint address ; - 0x11F2: Console output buffer pointer (default: 0x1104) ; - 0x11F4: Input buffer current position pointer ; - 0x11F6: Current prompt character (0x2A='*', 0x3E='>', 0x20=' ') ; - 0x11F7: Disk operation ready flag (0xFF = ready, 0x00 = not ready) ; - 0x11F8: Disk operation function pointer (0x0DAB = read, 0x0DB1 = write) ; ; • 0x1200-0x12FF: Hardware configuration and disk I/O control (256 bytes) ; DISK CONTROLLER CONFIGURATION BLOCK (0x1200-0x1227): ; - 0x1200-0x1201: DMA buffer address (16-bit, set by R/W commands) ; - 0x1202: Drive number (0-3, configured by O command) ; - 0x1203: Drive status/ready flags (0x01 = ready, used for DMA config) ; - 0x1205-0x1206: Status counter A (16-bit, initialized to 0xFFFF) ; - 0x1207-0x1208: Status counter B (16-bit, initialized to 0xFFFF) ; - 0x1209: Sector size parameter (default: 0x24 = 36 bytes per sector) ; - 0x120A: I/O port configuration (0xF0 = FDC port base settings) ; - 0x120B: Drive count/mode (0x03 = 3 drives or mode 3) ; - 0x120C: Additional FDC configuration and status data ; - 0x120D: FDC status register (used by disk operation status validation) ; - 0x120E: FDC extended status register (used by error condition checking) ; - 0x1213: FDC command byte (0x03 = READ, 0x04 = write, 0x0F = seek) ; - 0x1214: Drive/head selection (computed from 0x1226 + 0x1202) ; - 0x1215-0x1218: Track/sector parameter table (4 bytes, copied from l0c98h): ; • 0x1215: Byte 0 - Base configuration (0x00) ; • 0x1216: Byte 1 - Timing setting (0x1A) ; • 0x1217: Byte 2 - Mode flags (0xED) ; • 0x1218: Byte 3 - Control settings (0xE5) ; - 0x1223: Disk operation parameter storage (used by data tables) ; - 0x1225: Track number (0-76, configured by O command) ; - 0x1226: Drive control flags (0-1, configured by O command) ; - 0x1227: Sector count (1-26, configured by O command) ; - 0x1228-0x122B: Disk parameter lookup table 1 (4 bytes, copied from l0c90h): ; • 0x1228: Byte 0 - Base configuration value (0x00) ; • 0x1229: Byte 1 - Drive timing/control setting (0x1A) ; • 0x122A: Byte 2 - Drive mode flags (0x20) ; • 0x122B: Byte 3 - Drive status/control flags (0x80) ; - 0x122C-0x1241: DMA configuration block (22 bytes/0x16, copied from l0cfbh): ; • 0x122C-0x122E: Data bytes 0-2 (0xC3, 0xC3, 0xC3) ; • 0x122F-0x1231: Data bytes 3-5 (0xC3, 0xC3, 0xC3) ; • 0x1232: Data byte 6 (0x79) ; • 0x1233-0x1237: Data bytes 7-10 (padding: 0x00, 0x00, 0x00, 0x00) ; • 0x1238: Data byte 11 (0x14) ; • 0x1239-0x123A: Data bytes 12-13 (0x28, 0x89) ; • 0x123B-0x123D: Data bytes 14-16 (0xF2, 0x82, 0x83) ; • 0x123E: Data byte 17 (0xCF) ; • 0x123F-0x1241: Data bytes 18-20 (0x01, 0x83, 0xCF) ; ; • 0x1240-0x124F: FDC operation status and buffer management ; - 0x1242: SIO serial port configuration pointer (points to table at 0x0507) ; - 0x1243: Serial port base address configuration byte (used by I/O routines) ; - 0x1244-0x1245: 16-bit buffer pointer (low bank) - cleared to 0x0000 at startup ; - 0x1246-0x1247: 16-bit buffer pointer (mid bank) - cleared to 0x0000 at startup ; - 0x1248-0x1249: 16-bit buffer pointer (high bank) - cleared to 0x0000 at startup ; - 0x124A: FDC operation completion status (0 = pending, non-zero = done) ; - 0x124B: Additional FDC status and control parameters ; ; • 0x1300-0x132F: Interrupt vector table (IM2 mode, 48 bytes) ; - Contains interrupt vectors for SIO, DMA, and FDC operations ; - 0x1326: Breakpoint address backup (for memory paging operations) ; - 0x1334: Interrupt vector table pointer (used by DMA completion handler) ; ; • 0x1400-0x1FFF: System stack and buffers (1.5KB) ; - 0x1400: Stack pointer initialization point (grows downward) ; - Stack used for monitor operations, command processing, and user programs ; - Available memory: 0x1700-0x1FFF (2304 bytes) for user programs/data ; ; BANKED MEMORY SYSTEM: ; • 0x2000-0x3FFF: Paged RAM window (8KB, bank-switched) ; Access to 64KB external memory card via 8KB window ; Page selection via ports 0x000/0x003 (3-bit page number 0-7) ; Enables access to total 64KB external RAM in 8KB pages ; ;============================================================================== ; ; DISK I/O DATA TABLES SUMMARY: ; ROM Tables copied to RAM during disk operations: ; • l0c90h (ROM) → 0x1228-0x122B (4 bytes): Disk parameter lookup table 1 ; • l0c98h (ROM) → 0x1215-0x1218 (4 bytes): Track/sector parameter table ; • l0cfbh (ROM) → 0x122C-0x1241 (22 bytes): DMA configuration block ; ; Copy Operations performed by: ; • sub_0c73h: Copies l0c90h to 0x1228 (4 bytes via BC=0004h + LDIR) ; • sub_0c7bh: Copies l0c98h to 0x1215 (4 bytes via BC=0004h + LDIR) ; • Routine at 0cd7h: Copies l0cfbh to 0x122C (22 bytes via BC=0016h + LDIR) ; ;============================================================================== ; ; HARDWARE I/O PORT MAP: ;============================================================================== ; FLOPPY DISK CONTROLLER (NEC µPD765A): ; • Port 0xF0: FDC main status register (read-only) ; Bit 7: RQM (Request for Master) - FDC ready for command/data ; Bit 6: DIO (Data Input/Output) - Transfer direction ; Bit 5: NDM (Non-DMA Mode) - DMA/PIO mode indicator ; Bit 4: CB (Command Busy) - Command in progress ; Bits 0-3: Drive busy status (one bit per drive) ; ; • Port 0xF1: FDC data register (read/write) ; Command and parameter transfer port ; Data transfer during disk operations ; ; Z80 DMA CONTROLLER: ; • Port 0xF3: Z80 DMA command/status register (read/write) ; Used for high-speed disk data transfers ; Coordinates memory-to-peripheral data movement ; ; • Port 0xF4: Z80 DMA WR1 register (write-only) ; Memory address and byte count configuration ; Command 0x47: Address/count setup command ; ; • Port 0xF5: Z80 DMA WR3 register (write-only) ; Transfer mode, timing, and control settings ; Command 0x57: Transfer mode setup command ; ; • Port 0xFC: Z80 DMA controller command/parameter port ; Command 0x83: DMA control command for disk operations ; Used for DMA channel configuration and control ; ; MEMORY BANKING SYSTEM: ; • Port 0x000: Memory page selection (write-only) ; 3-bit page number (0-7) for 0x2000-0x3FFF window ; Enables access to 64KB external memory in 8KB pages ; ; • Port 0x003: Memory banking control (write-only) ; Additional banking control signals ; Used with port 0x000 for complete memory management ; ; SERIAL I/O CONTROLLER (SIO): ; • Ports 0x10-0x13: Z80 SIO/0 dual serial controller ; Channel A: Console terminal interface ; Channel B: Auxiliary serial port ; Supports interrupt-driven character I/O ; Automatic baud rate detection capability ;============================================================================== ; Used for programming the Z80 DMA with initialization sequences ; The hardware config table at 0x0F55 shows 19 bytes (count + 18 data bytes) ; written to this port to configure DMA operations ; Values 0x83/0xC3 are DMA command codes for control operations ; ; This monitor/debugger represents advanced 1980s software engineering with ; modular design, efficient algorithms, and professional user interface. ; ;############################################################################## ;Memory architecture: ;• 0x0000-0x0FFF: ROM code space (4KB 2716 EPROM) ;• 0x1000-0x13FF: Base RAM workspace (1KB) ;• 0x1242 SIO port config 0x0507 ;• 0x1300-0x1320: Interrupt vector table (IM2 mode) from 0x024f ;• 0x1400: Stack pointer start (grows downward toward RAM) ;• 0x2000-0x3FFF: Paged RAM window (8KB, bank-switched) ;• Extended RAM: 8x 4164 chips = 8 pages × 8KB = 64KB total ;• Page switching: Hardware register selects active 8KB bank ;• Effective memory: 1KB base + 8KB paged window + ROM ;============================================================================== ; MEMORY PAGING SYSTEM DOCUMENTATION ;============================================================================== ; The Metric 8 system implements a sophisticated memory paging mechanism to ; access a 64KB external memory card through an 8KB window at 0x2000-0x3FFF. ; ; CLEVER PORT SHARING STRATEGY: ; The system exploits the fact that ROM code only uses CTC Channels 1 and 2, ; leaving Channels 0 and 3 unused. Memory paging "hijacks" these unused ports ; without conflicting with essential CTC timing functions. ; ; PORT ALLOCATION STRATEGY: ; • PORT 0x000 (CTC Channel 0): UNUSED by ROM → Available for memory control ; • PORT 0x001 (CTC Channel 1): Used by ROM for timing functions ; • PORT 0x002 (CTC Channel 2): Used by ROM for SIO baud rate generation ; • PORT 0x003 (CTC Channel 3): UNUSED by ROM → Available for page selection ; ; MEMORY ARCHITECTURE: ; • Base System RAM: 1KB at 0x1000-0x13FF (always accessible) ; • Paged Memory Window: 8KB at 0x2000-0x3FFF (bank-switched via ports 0x000/0x003) ; • External Memory Card: 64KB organized as 8 pages × 8KB each ; • Total Addressable Memory: 1KB + 64KB = 65KB (plus ROM) ; ; CONTROL PORTS: ; • PORT 0x000: Memory Management Control Register (hijacks unused CTC Channel 0) ; - Bit 5 (0x20): Enable paging system ; - Controls overall memory management subsystem ; ; • PORT 0x003: Page Selection Register (hijacks unused CTC Channel 3) ; - 3-bit page number (0-7) selects which 8KB page appears at 0x2000-0x3FFF ; - Sequential writes may configure additional memory features ; ; COEXISTENCE WITH STANDARD HARDWARE: ; This design allows memory paging to work with standard SIO/CTC configuration: ; • SIO: ports 0x04-0x07 (unchanged) ; • CTC Channels 1&2: ports 0x01-0x02 (unchanged, ROM functions preserved) ; • Memory Management: ports 0x000 & 0x003 (reuse of unused CTC channels) ; • Result: 64KB memory card works with standard I/O configuration! ; ; OBSERVED PORT OPERATIONS: ; 1. out (000h),20h ; Enable memory management (bit 5 = paging enable) ; 2. out (003h),87h ; Select page 7 with setup flags (page + control bits) ; 3. out (003h),01h ; Select page 1 for actual operation ; 4. out (003h),03h ; Select page 3 (restore/cleanup page) ;============================================================================== ;I/O subsystem: ;• SIO 8440 chip for serial console (Pin 15 TxDA, Pin 17 RxDA) port 05-07 ;• MC1488/MC1489 RS-232 drivers (require ±12V) ;• CTC for baud rate generation and timing port 00-04 ;• Z80 DMA controller for high-speed floppy transfers - port 0xF3 ;• FDC NEC µPD765A for 8-inch floppy drives (77 tracks, 26 sectors/track): ; - 0xF0: FDC Main Status Register (read) ; - 0xF1: FDC Data Register (read/write via register C) ; - 0xF4: FDC Data Register (direct access) ; - 0xF6: FDC Command/Status Register ; - 0xFC: Additional FDC control ;• I/O ports accessed via register C org 00000h l0000h: jr l000eh ;0000 ; Boot entry: jump to initialization routine jp l00fdh ;0002 ; Main system routine (post-init) jp l0dabh ;0005 ; Error/exception handler or alternate entry jp l0294h ;0008 ; Memory test or hardware check jp l0de0h ;000b ; Interrupt/Z80 DMA handler or alternate l000eh: ld sp,01400h ;000e ; Set stack pointer to top of 1K SRAM (boot RAM) ld hl,01000h ;0011 ; HL points to start of SRAM ld de,01001h ;0014 ; DE points to next byte in SRAM ld bc,003ffh ;0017 ; BC = 1023 bytes (1K - 1) ld (hl),000h ;001a ; Zero first byte of SRAM ldir ;001c ; Zero entire 1K SRAM (boot RAM clear) ld a,013h ;001e ; Load interrupt vector base (IM2 table address) l0020h: ld i,a ;0020 ; Set Z80 interrupt vector register (IM2 base) im 2 ;0022 ; Set interrupt mode 2 (for SIO, Z80 DMA, FDC) call hw_init_01ach ;0024 ; Call hardware init (Z80 DMA, SIO, FDC setup) ld hl,l0507h ;0027 ; HL = pointer to boot string or table l002ah: jr nz,l002fh ;002a Fail hw test if it find some form of other thing then sio on port 04 06 l002ch: ld hl,0c3c1h ;002c This should be an alternate SIO card l002fh: ld (01242h),hl ;002f ; Save HL (alternate pointer) at 01242h for later use ld a,l ;0032 ; Load low byte of HL into A (may be used for error handling) ld hl,linterruptvector_table ;0033 ; Set HL to interrupt vector table address jr l003bh ;0036 ; Continue with boot sequence (alternate path) jp l07bch ;0038 ; Jump to CP/M loader or main OS entry if needed l003bh: ld de,01300h ;003b ; DE = destination Interruptvector addres ld bc,l0020h ;003e ; BC = length to copy (from l0020h) ldir ;0041 ; Block copy: transfer BC bytes from HL to DE ld hl,setupsio_table ;0043 ; HL = pointer to primary SIO configuration table cp 007h ;0046 ; Compare A to 7 (hardware detection/boot status) jr z,l004dh ;0048 ; If A == 7, use primary SIO card (normal case) ld hl,00214h ;004a ; If not, use secondary SIO card at high port addresses (0xC0+) l004dh: call setup_peripherals_01a1h ;004d ; Initialize peripherals (SIO) push hl ;0050 ; Save HL (pointer or error address) ld hl,01100h ;0051 ; HL = system buffer or stack sub a ;0054 ; Clear A (set to zero) ld (hl),a ;0055 ; Zero system buffer ei ;0056 Enable interrupts ; ROM code space l0057h: or (hl) ;0057 OR accumulator A with memory contents at address HL ; ROM code space,wait for keypress jr z,l0057h ;0058 Jump relative if Z to 0x0057 ; ROM code space di ;005a call sub_0149h ;005b ld a,030h ;005e //WR= error reset out (c),a ;0060 jr l0069h ;0062 rst 38h ;0064 rst 38h ;0065 jp l07b3h ;0066 ; Jump to interrupt/error handler - displays "BREAK AT " message l0069h: call sub_015dh ;0069 ; Call automatic baud rate detection and SIO configuration ld a,(01242h) ;006c cp 007h ;006f ld c,002h ;0071 ; Set C to 0x02 (standard CTC port) jr z,l0077h ;0073 ld c,0c4h ;0075 ; Set C to 0xC4 (alternate CTC port) l0077h: ;============================================================================== ; ADAPTIVE CTC CHANNEL INITIALIZATION (0x0079) ;============================================================================== ; Purpose: Configure CTC channel with automatic port selection and dual-phase setup ; Entry: sub_0079h - Called during hardware initialization sequence ; ; Input Registers: ; - A: 0x47 (CTC control word for initial configuration) ; - B: 0x02 (time constant value) ; - C: CTC port address (0x02 for standard, 0xC4 for alternate hardware) ; ; CTC Control Word 0x47 Breakdown: ; - Bit 7: 0 = Interrupt enable ; - Bit 6: 1 = Counter mode (not timer mode) ; - Bit 5: 0 = Prescaler ÷16 ; - Bit 4: 0 = Positive edge trigger ; - Bit 3: 1 = Time constant follows command ; - Bit 2: 1 = Software reset active ; - Bits 1-0: 11 = Control word identifier ; ; Two-Phase Operation: ; PHASE 1 (0x0079-0x007D): Send control word and time constant ; PHASE 2 (0x0087-0x008D): Send final control word (0x47) and divisor (0x02) ; ; Port Selection Logic: ; - Compares value from 0x1242 with 0x07 (SIO Channel B Control port) ; - If 0x1242 = 0x07: Uses standard mapping, C = 0x02 (CTC Channel 2) ; - If 0x1242 ≠ 0x07: Uses alternate mapping, C = 0xC4 (alternate CTC port) ; ; Hardware Compatibility: ; - Standard: SIO at 0x04-0x07, CTC at 0x00-0x03, configures CTC Channel 2 ; - Alternate: Different SIO ports, CTC at 0xC0-0xC7, configures alternate CTC ; ; Time Constant 0x02: ; - Divides input clock by 2 ; - Used for SIO clock generation (baud rate timing) ; - Combined with ÷16 prescaler = total division of 32 ; ; Integration: Part of larger peripheral initialization sequence ; Called after SIO detection and before final hardware setup ;============================================================================== ld a,047h ;0077 sub_0079h: out (c),a ;0079 Send CTC control word (0x47) to selected port out (c),b ;007b Send time constant (0x02) to CTC channel ld a,c ;007d Copy port address to A for comparison cp 0xc4 ;007f Compare with 0xC4 (alternate hardware marker) jr z,0x0085 ;0080 If alternate hardware, jump to port adjustment dec c ;0082 Standard hardware: decrement to previous channel jr 0x0087 ;0083 Continue to phase 2 initialization ; Alternate hardware port adjustment inc c ;0085 Increment port (0xC4 → 0xC5) inc c ;0086 Increment port (0xC5 → 0xC6) ; Phase 2: Final CTC configuration l0087h: ld a,047h ;0087 Reload CTC control word out (c),a ;0089 Send control word to final port ld a,002h ;008b Load final time constant/divisor out (c),a ;008d Send final configuration to CTC ;============================================================================== ; PHASE 3: COMPLETE HARDWARE INITIALIZATION AND SIO TESTING (0x008F+) ;============================================================================== ; After CTC setup, complete remaining peripheral initialization and test SIO ;============================================================================== ; Continue table-driven peripheral initialization pop hl ;008f Restore HL from stack (pointer to init table) inc hl ;0090 Advance to next table entry call setup_peripherals_01a1h ;0091 Continue table-driven peripheral setup ; Load test parameters and call diagnostic routine ld bc,058c0h ;0094 Load test parameters: B=0x58 (count), C=0xC0 (port/data) call sub_0f0ah ;0097 Call diagnostic/test routine with parameters ; SIO port preparation and buffer clearing call sub_0149h ;009a Get SIO port configuration (loads C with SIO control port) dec c ;009d Convert to SIO data port (control port - 1) in a,(c) ;009e Read SIO data port (clear any pending RX data) in a,(c) ;00a0 Read SIO data port again (ensure buffer clear) in a,(c) ;00a2 Third read to fully flush RX buffer ; Test SIO transmission capability call sub_0121h ;00a4 Send test character via SIO (verify TX works) ; Second SIO buffer clearing after transmission test dec c ;00a7 Set C back to SIO data port in a,(c) ;00a8 Read SIO data port (clear any echo/response data) in a,(c) ;00aa Read SIO data port again (ensure clean state) in a,(c) ;00ac Third read to fully flush post-transmission buffer ; Hardware initialization complete - enable interrupts and continue ei ;00ae Enable interrupts (hardware now fully operational) ; Print startup message after successful hardware initialization ld hl,l00e5h ;00af Load pointer to "Self diagnostics ..." message call l00fdh ;00b2 Print the startup message via serial port ; Run comprehensive system diagnostics call sub_0e89h ;00b5 Execute full system diagnostic suite ;============================================================================== ; SYSTEM CONFIGURATION MEMORY INITIALIZATION (0x00B8-0x00DF) ;============================================================================== ; Purpose: Initialize critical system configuration variables after diagnostics ; This section sets up default values for system operation parameters ;============================================================================== ld a,001h ;00b8 Load configuration value 0x01 ld (01203h),a ;00ba Store at 0x1203: Drive/status flags (bit 0 = drive ready) ld a,024h ;00bd Load configuration value 0x24 (36 decimal) ld (01209h),a ;00bf Store at 0x1209: Sector size parameter (36 bytes/sector?) ld a,0f0h ;00c2 Load configuration value 0xF0 (240 decimal) ld (0120ah),a ;00c4 Store at 0x120A: Port/channel configuration byte ld a,003h ;00c7 Load configuration value 0x03 ld (0120bh),a ;00c9 Store at 0x120B: Drive count or operation mode ld hl,l0000h ;00cc Load 16-bit value 0x0000 ld (01244h),hl ;00cf Store at 0x1244: Clear 16-bit buffer/pointer (low) ld (01246h),hl ;00d2 Store at 0x1246: Clear 16-bit buffer/pointer (mid) ld (01248h),hl ;00d5 Store at 0x1248: Clear 16-bit buffer/pointer (high) dec hl ;00d8 Decrement HL to 0xFFFF ld (01205h),hl ;00d9 Store at 0x1205: Initialize 16-bit counter/status (0xFFFF) ld (01207h),hl ;00dc Store at 0x1207: Initialize 16-bit counter/status (0xFFFF) call sub_0acbh ;00df Call additional hardware setup routine jp l0294h ;00e2 Jump to main system initialization ;============================================================================== ; STARTUP MESSAGE: "Self diagnostics ..." ;============================================================================== ; Displayed after successful hardware initialization to indicate system status ;============================================================================== l00e5h: defb "Self diagnostics ..." ;00e5-00f8 Startup message text defb 0xda ;00f9 Special character (Ú or box drawing) defb 0x0d ;00fa Carriage return defb 0x0a ;00fb Line feed defb 0x00 ;00fc Null terminator ;============================================================================== ; STRING OUTPUT ROUTINES - Console Display Functions ;============================================================================== ; Two different string output routines for different output methods ;============================================================================== ;============================================================================== ; PRINT STRING ROUTINE (0x00FD) - Standard Console Output ;============================================================================== ; Purpose: Print null-terminated string to console via standard output ; Input: HL = pointer to null-terminated string ; Output: String displayed on console via sub_0127h (console output with wait) ; Operation: Loops through string characters until null terminator found ; Used by: Main system messages, prompts, and user interface text ;============================================================================== l00fdh: ; Standard Print String Routine ld a,(hl) ;00fd Load character from string and a ;00fe Test for null terminator (sets Z flag if A=0) ret z ;00ff Return if end of string reached ld c,a ;0100 Move character to C register for output call sub_0127h ;0101 Call console output with wait (transmitter ready check) inc hl ;0104 Point to next character in string jr l00fdh ;0105 Loop back for next character ;============================================================================== ; ALTERNATE PRINT STRING ROUTINE (0x0107) - Direct Serial Output ;============================================================================== ; Purpose: Print null-terminated string via direct serial output method ; Input: HL = pointer to null-terminated string ; Output: String sent via sub_0111h (direct serial output) ; Operation: Similar to standard routine but uses different output method ; Used by: Low-level system messages or when console output unavailable ;============================================================================== l0107h: ; Alternate Print String Routine ld a,(hl) ;0107 Load character from string and a ;0108 Test for null terminator (sets Z flag if A=0) ret z ;0109 Return if end of string reached ld c,a ;010a Move character to C register for output call sub_0111h ;010b Call direct serial output routine inc hl ;010e Point to next character in string jr l0107h ;010f Loop back for next character ;============================================================================== ; DIRECT SERIAL OUTPUT ROUTINE (0x0111) ;============================================================================== ; Purpose: Output character directly to serial port without full handshaking ; Input: C = character to output ; Operation: Calls sub_0121h then jumps to l012ah for immediate transmission ;============================================================================== sub_0111h: ; Direct Serial Output call sub_0121h ;0111 Set up serial port configuration jr l012ah ;0114 Jump to immediate output routine ;============================================================================== ; SERIAL INPUT WITH WAIT (0x0116) ;============================================================================== ; Purpose: Wait for and read character from serial input ; Output: C = received character ; Operation: Loops until character available, then returns it ;============================================================================== l0116h: ; Serial Input with Wait call sub_011ch ;0116 Check for input character available jr z,l0116h ;0119 Loop if no character available (Z flag set) ret ;011b Return with character in C register ;============================================================================== ; CHECK SERIAL INPUT READY (0x011C) ;============================================================================== ; Purpose: Check if serial input character is available (non-blocking) ; Output: Z flag = set if no character, clear if character available ; C = character (if available) ; Operation: Tests serial port status and reads character if present ;============================================================================== sub_011ch: ; Check Serial Input Ready call sub_0121h ;011c Set up serial port configuration jr l013dh ;011f Jump to input status check routine ;============================================================================== ; SERIAL PORT SETUP ROUTINE (0x0121) ;============================================================================== ; Purpose: Set up serial port configuration for I/O operations ; Input: C = character to be output (preserved in B register) ; Output: C = serial port address from configuration byte at 0x1243 ; Operation: Saves character, loads port address, prepares for I/O ;============================================================================== sub_0121h: ; Serial Port Setup ld b,c ;0121 Save character/input parameter in B register ld a,(01243h) ;0122 Load serial port base address from config byte l0125h: ld c,a ;0125 Move port address to C register ret ;0126 Return with port address in C, character in B ;ROUTINE: Console Output with Wait (0x0127) ;-------------------------------------------- ;Purpose: Outputs character and waits for transmitter ready sub_0127h: call sub_0149h ;0127 Get serial port base address l012ah: in a,(c) ;012a Read status register bit 2,a ;012c Test transmitter ready bit jr z,l012ah ;012e Wait if not ready dec c ;0130 Point to data register out (c),b ;0131 Output character ret ;0133 Return to caller l0134h: call sub_013ah ;0134 Check for input character available jr z,l0134h ;0137 Loop if no character available (Z flag set) ret ;0139 Return with character received ;============================================================================== ; CHECK SERIAL INPUT READY (0x013A) - Non-blocking Input Status Check ;============================================================================== ; Purpose: Check if serial input character is available without blocking ; Output: Z flag = set if no character, clear if character available ; C = character data (if available), A = character (7-bit masked) ; Operation: Tests serial port RX status bit, reads and processes character ;============================================================================== sub_013ah: ; Check Serial Input Ready (Non-blocking) call sub_0149h ;013a Get serial port base address in C register l013dh: ; Input status check entry point in a,(c) ;013d Read status register from serial port bit 0,a ;013f Test bit 0 (receiver ready/character available) ret z ;0141 Return with Z flag set if no character available dec c ;0142 Decrement C to point to data register (status+1=data) in a,(c) ;0143 Read character from serial port data register and 07fh ;0145 Mask to 7 bits (remove parity/high bit) sub_0147h: ; Character processing entry point ld c,a ;0147 Store character in C register for caller ret ;0148 Return with character in both A and C registers ;============================================================================== ; GET SERIAL PORT BASE ADDRESS (0x0149) - Port Configuration Setup ;============================================================================== ; Purpose: Load serial port base address from configuration and set up registers ; Input: C = current value (preserved in B) ; Output: C = serial port base address, B = saved previous C value ; Operation: Loads port address from config pointer at 0x1242 ;============================================================================== sub_0149h: ; Get Serial Port Base Address ld b,c ;0149 Save current C register value in B ld a,(01242h) ;014a Load serial port configuration from memory ld c,a ;014d Set C to serial port base address ret ;014e Return with port address in C, old value in B ;============================================================================== ; ECHO/BRIDGE MODE (0x014F) - Bidirectional Serial Bridge ;============================================================================== ; Purpose: Implement echo or serial bridge functionality between ports ; Operation: Infinite loop that transfers data bidirectionally ; Used for: Terminal echo, serial port bridging, or communication testing ;============================================================================== l014fh: ; Echo/Bridge Mode Entry Point call sub_013ah ;014f Check for input character from serial port call nz,sub_0111h ;0152 If character received, output it (echo/bridge) call sub_011ch ;0155 Check for input from alternate source call nz,sub_0127h ;0158 If character received, output via console jr l014fh ;015b Loop continuously (infinite bridge mode) ;============================================================================== ; AUTOMATIC BAUD RATE CALCULATOR AND SIO CONFIGURATOR (0x015D) ;============================================================================== ; Purpose: Dynamically calculate and configure SIO baud rate based on timing measurements ; Entry: sub_015dh - Called after serial character timing measurements ; ; Input Values: ; - 0x1100: 8-bit timing measurement (character bit timing) ; - 0x1101-0x1102: 16-bit timing measurement (character/timeout count) ; ; Algorithm: ; 1. SCALING PHASE: ; - Loads 16-bit timing value from 0x1101-0x1102 into HL ; - Multiplies HL by 8 (three left shifts) to scale timing value ; - Loads 8-bit measurement from 0x1100 into A ; ; 2. MAGNITUDE DETECTION: ; - Performs arithmetic right shifts on A while incrementing HL ; - Counts significant bits to determine timing magnitude ; - Stops when carry flag set (found first '1' bit) ; - Result: BC = scaled timing value for table lookup ; ; 3. TABLE LOOKUP: ; - Searches baud rate table at l0183h (contains standard timing values) ; - Each table entry: 16-bit timing threshold + 8-bit SIO divisor value ; - Finds best matching standard baud rate for measured timing ; - Uses binary search approach with carry flag comparison ; ; 4. SIO CONFIGURATION: ; - Returns A = 0x44 (SIO WR4 register value: 1 stop bit, 16x clock) ; - Returns B = clock divisor value from table ; ; Table Format (l0183h): ; Each 3-byte entry: [Low_Threshold] [High_Threshold] [SIO_Divisor] ; - Thresholds define timing ranges for standard baud rates ; - SIO_Divisor used in WR4 register for clock generation ; ; Auto-Detection Process: ; - System measures actual bit timing from incoming serial data ; - This routine converts measurements to appropriate SIO clock settings ; - Enables automatic baud rate detection without manual configuration ; ; Applications: ; - Auto-configure terminal connections ; - Adapt to different computer baud rates automatically ; - Robust serial communication without preset requirements ; ; Returns: A = 0x44 (WR4 value), B = clock divisor, timing configured ; Notes: Sophisticated floating-point-like integer math for 1980s hardware ;============================================================================== sub_015dh: ; Automatic Baud Rate Calculator Entry Point ld hl,(01101h) ;015d Load 16-bit timing measurement from memory ld a,(01100h) ;0160 Load 8-bit character timing measurement add hl,hl ;0163 Multiply HL by 8 (scale timing value) add hl,hl ;0164 Left shift 1: HL = HL * 2 add hl,hl ;0165 Left shift 2: HL = HL * 4, total = original * 8 l0166h: ; Magnitude detection loop sra a ;0166 Arithmetic right shift A (find first significant bit) inc hl ;0168 Increment HL counter for each bit shift jr nc,l0166h ;0169 Continue until carry set (found first '1' bit) ld c,l ;016b Store low byte of scaled timing in C ld b,h ;016c Store high byte of scaled timing in B (BC = timing) ld hl,l0183h ;016d Point to baud rate lookup table start sub a ;0170 Clear A register (will count table entries) l0171h: ; Table search loop inc a ;0171 Increment table entry counter ld e,(hl) ;0172 Load low byte of timing threshold from table inc hl ;0173 Move to next byte in table ld d,(hl) ;0174 Load high byte of timing threshold (DE = threshold) inc hl ;0175 Move to next table entry ex de,hl ;0176 Exchange: HL = threshold, DE = table pointer and a ;0177 Clear carry flag for subtraction sbc hl,bc ;0178 Compare threshold with measured timing (HL - BC) ex de,hl ;017a Restore: HL = table pointer, DE = difference inc hl ;017b Move to divisor byte in current table entry jr c,l0171h ;017c If threshold < timing, try next table entry dec hl ;017e Back up to divisor byte of matching entry ld b,(hl) ;017f Load SIO clock divisor value into B register ld a,044h ;0180 Load SIO WR4 register value (1 stop bit, 16x clock) ret ;0182 Return with A = WR4 value, B = clock divisor ;============================================================================== ; BAUD RATE DETECTION TABLE (0x0183-0x01A0) ;============================================================================== ; Format: Each 3-byte entry contains [Low_Limit] [High_Limit] [SIO_Divisor] ; Used by automatic baud rate detection routine at sub_015dh ; Entries ordered from fastest to slowest baud rates for binary search ;============================================================================== l0183h: ; Entry 1: High speed range defb 0x10, 0x01, 0x2C ;0183-0185 ; Limits: 0x0110-0x012C, Divisor: 0x2C (44) ; Entry 2: defb 0x5C, 0x00, 0x04 ;0186-0188 ; Limits: 0x005C-0x0004, Divisor: 0x04 (4) ; Entry 3: defb 0xBC, 0x00, 0x08 ;0189-018B ; Limits: 0x00BC-0x0008, Divisor: 0x08 (8) ; Entry 4: defb 0x7C, 0x01, 0x10 ;018C-018E ; Limits: 0x017C-0x0110, Divisor: 0x10 (16) ; Entry 5: defb 0xFC, 0x02, 0x20 ;018F-0191 ; Limits: 0x02FC-0x0220, Divisor: 0x20 (32) ; Entry 6: defb 0x05, 0x40, 0x70 ;0192-0194 ; Limits: 0x4005-0x7040, Divisor: 0x70 (112) ; Entry 7: defb 0x09, 0x80, 0x70 ;0195-0197 ; Limits: 0x8009-0x7080, Divisor: 0x70 (112) ; Entry 8: defb 0x0C, 0xA0, 0xFF ;0198-019A ; Limits: 0xA00C-0xFFA0, Divisor: 0xFF (255) ; Entry 9: Low speed range defb 0xFF, 0xFF, 0x00 ;019B-019D ; Limits: 0xFFFF-0x00FF, Divisor: 0x00 (0) ; Table terminator defb 0xFF, 0xFF ;019E-019F ; End marker defb 0x00 ;01A0 ; Padding/terminator setup_peripherals_01a1h: ld a,(hl) ;01a1 ; Load count from table (A = number of bytes to output) and a ;01a2 ; Test if count is zero ret z ;01a3 ; If zero, end of table, return ld b,a ;01a4 ; Set B = count inc hl ;01a5 ; Move to next table entry ld c,(hl) ;01a6 ; Load port number from table inc hl ;01a7 ; Move to data bytes otir ;01a8 ; Output B bytes from (HL) to port C, increment HL each time jr setup_peripherals_01a1h ;01aa ; Repeat for next table entry hw_init_01ach: ;Probably check if there is a perifle that can be read and write to which is not a SIO ld hl,initsio_l01d9h ;01ac ; HL = pointer to hardware register or test value call setup_peripherals_01a1h ;01af ; Call additional hardware init routine ld c,004h ;01b2 ; Set port C = 0x04 (SIO A data port) ld a,055h ;01b4 ; Load test pattern 0x55 call check_peri_01d2h ;01b6 ; Output 0x55 to port 0x04 (SIO A data port) ret nz ;01b9 ; If error, return ld a,0aah ;01ba ; Load test pattern 0xAA call check_peri_01d2h ;01bc ; Output 0xAA to port 0x04 (SIO A data port) ret nz ;01bf ; If error, return ld a,055h ;01c0 ; Load test pattern 0x55 ld c,006h ;01c2 ; Set port C = 0x06 (SIO B data port) call check_peri_01d2h ;01c4 ; Output 0x55 to port 0x06 and 00fh ;01c7 ; Mask lower nibble (hardware check) ret nz ;01c9 ; If error, return ld a,0aah ;01ca ; Load test pattern 0xAA call check_peri_01d2h ;01cc ; Output 0xAA to port 0x06 (SIO B data port) and 00fh ;01cf ; Mask lower nibble (hardware check) ret ;01d1 ; Return (hardware init complete) check_peri_01d2h: out (c),a ;01d2 ; Output value in A to port C ld b,a ;01d4 ; Save value in B in a,(c) ;01d5 ; Read value back from port C into A xor b ;01d7 ; Compare read value with what was written ret ;01d8 ; Return initsio_l01d9h: ; PRIMARY SIO CARD initialization table (ports 0x04-0x07) ; This is the first/preferred SIO card on the bus defb 0x02 ;01d9 ; Count: 2 bytes to output defb 0x05 ;01da ; Port: 0x05 (Primary SIO Channel A Control) defb 0xCF ;01db ; Data byte 1: WR 7, SEND ABORT (SDLC), RESET Tx UNDERRUN/EOM LATCH defb 0x00 ;01dc ; Data byte 2: SYNC BIT 8-15 = 0 defb 0x02 ;01dd ; Count: 2 bytes to output defb 0x07 ;01de ; Port: 0x07 (Primary SIO Channel B Control) defb 0xCF ;01df ; Data byte 1: WR 7, SEND ABORT (SDLC), RESET Tx UNDERRUN/EOM LATCH defb 0xF0 ;01e0 ; Data byte 2: Reset channel B sync bit 12-15 defb 0x00 ;01e1 ; END marker setupsio_table: l01e2h: ; CTC setup for SIO timing defb 0x02 ;01e2 ; 2 bytes to output defb 0x02 ;01e3 ; CTC Channel 2 (provides clock for SIO) defb 0x47 ;01e4 ; CTC Control: Software reset, Time constant follows, Prescaler=16, Counter mode defb 0x01 ;01e5 ; Time constant = 1 (fast clock for SIO) ; PRIMARY SIO CHANNEL B (Console/Terminal) - Complete WR Configuration defb 0x11 ;01e6 ; 17 bytes to configure Channel B defb 0x07 ;01e7 ; Port 0x07 (Primary SIO Channel B Control) ; WR0 Commands and Register Selection defb 0x58 ;01e8 ; WR0: 01011000b = Channel Reset + Reset Rx CRC Checker defb 0x02 ;01e9 ; WR0: 00000010b = Select WR2 for next write defb 0x00 ;01ea ; WR2: Interrupt vector = 0x00 (disable interrupts) defb 0x04 ;01eb ; WR0: 00000100b = Select WR4 for next write defb 0x10 ;01ec ; WR4: 00010000b = 16x clock, No parity, 1 stop bit, No sync defb 0x15 ;01ed ; WR0: 00010101b = Select WR5 + Send Abort (SDLC mode prep) defb 0x84 ;01ee ; WR5: 10000100b = DTR active, 8 bits/char, Tx disabled initially, No RTS yet defb 0x03 ;01ef ; WR0: 00000011b = Select WR3 + Reset External Status interrupts defb 0xd2 ;01f0 ; WR3: 11010010b = Rx 8 bits, Enter Hunt Phase, Sync Char Load Inhibit, Rx disabled initially defb 0x06 ;01f1 ; WR0: 00000110b = Select WR6 for next write defb 0xff ;01f2 ; WR6: Sync Character bits 0-7 = 0xFF (sync pattern low byte) defb 0x07 ;01f3 ; WR0: 00000111b = Select WR7 for next write defb 0x0f ;01f4 ; WR7: Sync Character bits 8-15 = 0x0F (sync pattern high byte) defb 0x11 ;01f5 ; WR0: 00010001b = Select WR1 + Reset External Status interrupts defb 0x0c ;01f6 ; WR1: 00001100b = Status affects vector, Rx INT on first char or special condition defb 0x23 ;01f7 ; WR0: 00100011b = Select WR3 + Enable INT on next Rx char defb 0xd3 ;01f8 ; WR3: 11010011b = Rx Enable, 8 bits, Enter Hunt Phase, Sync Char Load Inhibit defb 0x00 ;01f9 ; END marker l01fa: ; PRIMARY SIO CHANNEL B (Console) - Simplified Setup for Normal Operation defb 0x0c ;01fa ; 12 bytes to configure Channel B for basic async operation defb 0x07 ;01fb ; Port 0x07 (Primary SIO Channel B Control) defb 0x18 ;01fc ; WR0: 00011000b = Channel Reset (clear all state) defb 0x02 ;01fd ; WR0: 00000010b = Select WR2 for next write defb 0x00 ;01fe ; WR2: Interrupt vector = 0x00 (no interrupts) defb 0x18 ;01ff ; WR0: 00011000b = Channel Reset (ensure clean state) defb 0x01 ;0200 ; WR0: 00000001b = Select WR1 for next write defb 0x04 ;0201 ; WR1: 00000100b = Status affects interrupt vector defb 0x04 ;0202 ; WR0: 00000100b = Select WR4 for next write defb 0x44 ;0203 ; WR4: 01000100b = 16x clock, 1 stop bit, No parity, 8 bits defb 0x03 ;0204 ; WR0: 00000011b = Select WR3 + Reset External Status defb 0xc1 ;0205 ; WR3: 11000001b = Rx Enable, 8 bits/char, No auto enables defb 0x05 ;0206 ; WR0: 00000101b = Select WR5 defb 0xea ;0207 ; WR5: 11101010b = RTS, DTR, Tx Enable, 8 bits/char, Break ; PRIMARY SIO CHANNEL A (Auxiliary/Data) - Basic Setup defb 0x09 ;0208 ; 9 bytes to configure Channel A defb 0x05 ;0209 ; Port 0x05 (Primary SIO Channel A Control) defb 0x18 ;020a ; WR0: 00011000b = Channel Reset defb 0x01 ;020b ; WR0: 00000001b = Select WR1 for next write defb 0x00 ;020c ; WR1: 00000000b = No interrupts, no status affects vector defb 0x04 ;020d ; WR0: 00000100b = Select WR4 for next write defb 0x44 ;020e ; WR4: 01000100b = 16x clock, 1 stop bit, No parity, 8 bits defb 0x03 ;020f ; WR0: 00000011b = Select WR3 + Reset External Status defb 0xc1 ;0210 ; WR3: 11000001b = Rx Enable, 8 bits/char defb 0x05 ;0211 ; WR0: 00000101b = Select WR5 defb 0xea ;0212 ; WR5: 11101010b = RTS, DTR, Tx Enable, 8 bits/char, Break defb 0x00 ;0213 ; END marker l0214h: ; SECONDARY SIO CARD initialization table (ports 0xC0-0xC4) ; This is an alternate SIO card on the bus, used if primary SIO fails defb 0x02 ;0214 ; 2 bytes to output defb 0x02 ;0215 ; CTC channel (shared timing for secondary SIO) defb 0x47 ;0216 ; CTC Control: SW reset, Time constant follows, Prescaler=16, Counter mode defb 0x04 ;0217 ; Time constant = 4 (different timing from primary) defb 0x02 ;0218 ; 2 bytes to output defb 0xc4 ;0219 ; Port 0xC4 (Secondary SIO Channel A Control - high address mapping) defb 0x47 ;021a ; Command: 01000111b = Select WR4 + Software reset + Time constant defb 0x01 ;021b ; Parameter value ; SECONDARY SIO CHANNEL B (Console backup) - Initial Setup defb 0x05 ;021c ; 5 bytes to output defb 0xc3 ;021d ; Port 0xC3 (Secondary SIO Channel B Control - high address mapping) defb 0x58 ;021e ; WR0: 01011000b = Channel Reset + Reset Rx CRC Checker defb 0x02 ;021f ; WR0: 00000010b = Select WR2 for next write defb 0x10 ;0220 ; WR2: Interrupt vector = 0x10 (different from primary) defb 0x01 ;0221 ; WR0: 00000001b = Select WR1 for next write defb 0x04 ;0222 ; WR1: 00000100b = Status affects interrupt vector ; SECONDARY SIO CHANNEL A (Data backup) - Complete Configuration defb 0x0f ;0223 ; 15 bytes to output (extensive SIO configuration) defb 0xc1 ;0224 ; Port 0xC1 (Secondary SIO Channel A Control - high address mapping) defb 0x58 ;0225 ; WR0: 01011000b = Channel Reset + Reset Rx CRC Checker defb 0x04 ;0226 ; WR0: 00000100b = Select WR4 for next write defb 0x10 ;0227 ; WR4: 00010000b = 16x clock, No parity, 1 stop bit defb 0x15 ;0228 ; WR0: 00010101b = Select WR5 + Send Abort (SDLC prep) defb 0x84 ;0229 ; WR5: 10000100b = DTR active, 8 bits/char, Tx disabled initially defb 0x03 ;022a ; WR0: 00000011b = Select WR3 + Reset External Status defb 0xd2 ;022b ; WR3: 11010010b = Rx 8 bits, Enter Hunt Phase, Sync Char Load Inhibit defb 0x06 ;022c ; WR0: 00000110b = Select WR6 for next write defb 0xFF ;022d ; WR6: Sync Character bits 0-7 = 0xFF defb 0x07 ;022e ; WR0: 00000111b = Select WR7 for next write defb 0x0f ;022f ; WR7: Sync Character bits 8-15 = 0x0F defb 0x11 ;0230 ; WR0: 00010001b = Select WR1 + Reset External Status defb 0x0c ;0231 ; WR1: 00001100b = Status affects vector, Rx INT on first char defb 0x23 ;0232 ; WR0: 00100011b = Select WR3 + Enable INT on next Rx char defb 0xd3 ;0233 ; WR3: 11010011b = Rx Enable, 8 bits, Enter Hunt Phase defb 0x00 ;0234 ; END marker l0235h: ; SECONDARY SIO - Final Configuration for Normal Operation ; Simplified setup for basic async operation on backup SIO card defb 0x0c ;0235 ; 12 bytes to output defb 0xc3 ;0236 ; Port 0xC3 (Secondary SIO Channel B Control) defb 0x18 ;0237 ; WR0: 00011000b = Channel Reset (clear all state) defb 0x02 ;0238 ; WR0: 00000010b = Select WR2 for next write defb 0x10 ;0239 ; WR2: Interrupt vector = 0x10 (secondary interrupt vector) defb 0x18 ;023a ; WR0: 00011000b = Channel Reset (ensure clean state) defb 0x01 ;023b ; WR0: 00000001b = Select WR1 for next write defb 0x04 ;023c ; WR1: 00000100b = Status affects interrupt vector defb 0x04 ;023d ; WR0: 00000100b = Select WR4 for next write defb 0x44 ;023e ; WR4: 01000100b = 16x clock, 1 stop bit, No parity, 8 bits defb 0x03 ;023f ; WR0: 00000011b = Select WR3 + Reset External Status defb 0xc1 ;0240 ; WR3: 11000001b = Rx Enable, 8 bits/char, No auto enables defb 0x05 ;0241 ; WR0: 00000101b = Select WR5 defb 0xea ;0242 ; WR5: 11101010b = RTS, DTR, Tx Enable, 8 bits/char, Break ; SECONDARY SIO CHANNEL A - Basic Setup defb 0x09 ;0243 ; 9 bytes to output defb 0xc1 ;0244 ; Port 0xC1 (Secondary SIO Channel A Control) defb 0x18 ;0245 ; WR0: 00011000b = Channel Reset defb 0x01 ;0246 ; WR0: 00000001b = Select WR1 for next write defb 0x00 ;0247 ; WR1: 00000000b = No interrupts, no status affects vector defb 0x04 ;0248 ; WR0: 00000100b = Select WR4 for next write defb 0x44 ;0249 ; WR4: 01000100b = 16x clock, 1 stop bit, No parity, 8 bits defb 0x03 ;024a ; WR0: 00000011b = Select WR3 + Reset External Status defb 0xc1 ;024b ; WR3: 11000001b = Rx Enable, 8 bits/char defb 0x05 ;024c ; WR0: 00000101b = Select WR5 defb 0xea ;024d ; WR5: 11101010b = RTS, DTR, Tx Enable, 8 bits/char, Break defb 0x00 ;024e ; END marker ;============================================================================== ; INTERRUPT VECTOR TABLE FOR SIO OPERATIONS ;============================================================================== ; These vectors are loaded into RAM at 0x1300+ for interrupt mode 2 operation ; Provides specific handlers for different SIO interrupt conditions ;============================================================================== defb 0x91 ;024f ; Interrupt vector base (0x1300) defb 0x02 ;0250 ; Interrupt linterupt2vector 0x1301 defb 0x92 ;0251 ; Interrupt vector 0x1302 defb 0x02 ;0252 ; Interrupt linterupt2vector 0x1303 defb 0x6f ;0253 ; Interrupt vector 0x1304 defb 0x02 ;0254 ; Interrupt linterupt1vector 0x1305 defb 0x91 ;0255 ; Interrupt vector 0x1306 defb 0x02 ;0256 ; Interrupt linterupt2vector 0x1307 defb 0x91 ;0257 ; Interrupt vector 0x1308 defb 0x02 ;0258 ; Interrupt linterupt2vector 0x1309 defb 0x91 ;0259 ; Interrupt vector 0x130a defb 0x02 ;025a ; Interrupt linterupt2vector 0x130b defb 0x91 ;025b ; Interrupt vector 0x130c defb 0x02 ;025c ; Interrupt linterupt2vector 0x130d defb 0x91 ;025d ; Interrupt vector 0x130e defb 0x02 ;025e ; Interrupt linterupt2vector 0x130f defb 0x91 ;025f ; Interrupt vector 0x1310 defb 0x02 ;0260 ; Interrupt linterupt2vector 0x1311 defb 0x91 ;0261 ; Interrupt vector 0x1312 defb 0x02 ;0262 ; Interrupt linterupt2vector 0x1313 defb 0x91 ;0263 ; Interrupt vector 0x1314 defb 0x02 ;0264 ; Interrupt linterupt2vector 0x1315 defb 0x91 ;0265 ; Interrupt vector 0x1316 defb 0x02 ;0266 ; Interrupt linterupt2vector 0x1317 defb 0x91 ;0267 ; Interrupt vector 0x1318 defb 0x02 ;0268 ; Interrupt linterupt2vector 0x1319 defb 0x91 ;0269 ; Interrupt vector 0x1320 defb 0x02 ;026A ; Interrupt linterupt2vector 0x1321 defb 0x6f ;026B ; Interrupt vector 0x1322 defb 0x02 ;026C ; Interrupt linterupt1vector 0x1323 defb 0x91 ;026D ; Interrupt vector 0x1324 defb 0x02 ;026E ; Interrupt linterupt2vector 0x1325 linterupt1: push af ;026f ; Save accumulator and flags push bc ;0270 ; Save BC register pair call sub_0149h ;0271 ; Setup: loads serial port address into C (from 0x1242), C=command/status port push hl ;0274 ; Save HL register pair ld hl,l0000h ;0275 ; HL = 0 (used as a counter for timeout/retries) l0278h: dec c ;0278 ; C = C - 1 (now C=data port) in a,(c) ;0279 ; Read data register from port C or a ;027b ; Set flags based on A (is data nonzero?) jr nz,l0288h ;027c ; If data != 0, jump to l0288h (data ready) inc hl ;027e ; HL = HL + 1 (increment timeout/retry counter) inc c ;027f ; C = C + 1 (restore C to command/status port,) l0280h: in a,(c) ;0280 ; Read command/status register from port C, bit 0,a ;0282 ; Test bit 0 (is data available/ready) Rx CHARACTER AVAILABLE jr nz,l0278h ;0284 ; If bit 0 set, go back to data port read jr l0280h ;0286 ; Otherwise, keep polling command/status port l0288h: ld (01100h),a ;0288 ; Store received byte in 0x1100 ld (01101h),hl ;028b ; Store HL (timeout/retry count) in 0x1101/0x1102 pop hl ;028e ; Restore HL (was used as counter) pop bc ;028f ; Restore BC pop af ;0290 ; Restore AF linterupt2: ei ;0291 ; Enable interrupts reti ;0292 ; Return from interrupt ; -------------------------------------------------- ; 0x0294: System Initialization Block ; - Sets stack pointer to 0x1400 ; - Loads interrupt vector (A=0x13), sets I register ; - Sets interrupt mode 2 and enables interrupts ; - Calls sub_0770h to save CPU context and further setup ; -------------------------------------------------- l0294h: ld sp,01400h ;0294 ld a,013h ;0297 ld i,a ;0299 im 2 ;029b ei ;029d call sub_0770h ;029e ; -------------------------------------------------- ; After 0x029e: Continued System/Memory Initialization ; - Sets HL to 01100h, stores at 011ech ; - Sets HL to l0000h, stores at 011f0h ; - Sets HL to l0fech, calls l00fdh (setup/copy routine) ; - Sets HL to 01104h, stores at 011f2h ; - Loads A with 0x2A, stores at 011f6h ; - Calls sub_080dh (setup/test routine) ; - Branches: if NZ, jumps to l02c9h; else, jumps to l0fbbh ; Purpose: Finalizes pointers, memory, and hardware setup, then tests/branches on result ; -------------------------------------------------- ld hl,01100h ;02a1 ld (011ech),hl ;02a4 ld hl,l0000h ;02a7 ld (011f0h),hl ;02aa ld hl,l0fech ;02ad Load HL with address of version string ("Ver 1.2x 8 inch") call l00fdh ;02b0 Print version string to console via standard output routine ld hl,01104h ;02b3 Set HL to console buffer address (0x1104) ld (011f2h),hl ;02b6 Store console buffer pointer at 0x011F2 ld a,02ah ;02b9 ld (011f6h),a ;02bb call sub_080dh ;02be jr nz,l02c9h ;02c1 jp l0fbbh ;02c3 l02c6h: call sub_080dh ;02c6 Get user input from console l02c9h: call sub_02e4h ;02c9 Execute parsed command (dual-purpose code) ; ============================================================================= ; MAIN MONITOR COMMAND LOOP - Heart of the Debug System ; ============================================================================= ; Purpose: Main command prompt and processing loop for the monitor/debugger ; Operation: Sets up input buffer, displays '>' prompt, processes commands ; Flow: All monitor commands (dump, compare, breakpoint, etc.) return here ; This is the central control point of the entire monitor system ; ============================================================================= l02cch: ; Main Monitor Command Loop Entry Point ld hl,01104h ;02cc Point to console input buffer start ld (011f2h),hl ;02cf Store input buffer pointer for system use ld a,03eh ;02d2 Load '>' character (0x3E = ASCII prompt) ld (011f6h),a ;02d4 Store prompt character for display jr l02c6h ;02d7 Jump to input processing (creates command loop) l02d9h: ld sp,01400h ;02d9 ld hl,l0323h ;02dc call l00fdh ;02df jr l02cch ;02e2 ;============================================================================== ; DUAL-PURPOSE CODE/DATA TABLE (0x02E4-0x0322) ;============================================================================== ; This section serves as BOTH executable code AND data table! ; ; AS EXECUTABLE CODE (when called from 0x02C9): ; - 0x02E4: CD 4C 06 call sub_064ch ; - 0x02E7: 13 inc de ; - 0x02E8: 42 ld b,d ; - 0x02E9: E2 03 43 jp po,4303h ; - etc. ; ; AS DATA TABLE (when accessed as bytes): ; Contains ASCII character sequence B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,W,X ; This appears to be a character encoding or command lookup table ; ; This technique was common in 1980s ROMs to save precious memory space ; by making code serve dual purposes as both instructions and data ;============================================================================== sub_02e4h: ; Entry point when called as subroutine call sub_064ch ;02e4 CD 4C 06 ; ============================================================================= ; COMMAND TABLE - Monitor Command Lookup Table ; ============================================================================= ; Purpose: Table of valid monitor commands with their handler addresses ; Structure: Count byte, followed by entries of (ASCII char, address low, address high) ; Used by: sub_064ch to parse and dispatch monitor commands ; ============================================================================= command_table: defb 015h ;02e7 Command count (21 commands) defb 042h ;02e8 'B' (ASCII 'B') defb 0e2h, 003h ;02e9 Address 0x03e2 for B command defb 043h ;02eb 'C' (ASCII 'C') defb 023h, 003h ;02ec Address 0x0323 for C command defb 044h ;02ee 'D' (ASCII 'D') defb 058h, 003h ;02ef Address 0x0358 for D command defb 045h ;02f1 'E' (ASCII 'E') defb 015h, 005h ;02f2 Address 0x0515 for E command defb 046h ;02f4 'F' (ASCII 'F') defb 0b7h, 003h ;02f5 Address 0x03b7 for F command defb 047h ;02f7 'G' (ASCII 'G') defb 04ah, 004h ;02f8 Address 0x044a for G command defb 048h ;02fa 'H' (ASCII 'H') defb 087h, 008h ;02fb Address 0x0887 for H command defb 049h ;02fd 'I' (ASCII 'I') defb 0cfh, 003h ;02fe Address 0x03cf for I command defb 04ah ;0300 'J' (ASCII 'J') defb 041h, 004h ;0301 Address 0x0441 for J command defb 04ch ;0303 'L' (ASCII 'L') defb 09fh, 008h ;0304 Address 0x089f for L command defb 04dh ;0306 'M' (ASCII 'M') defb 0fch, 004h ;0307 Address 0x04fc for M command defb 04eh ;0309 'N' (ASCII 'N') defb 09fh, 004h ;030a Address 0x049f for N command defb 04fh ;030c 'O' (ASCII 'O') defb 0bch, 009h ;030d Address 0x09bc for O command defb 050h ;030f 'P' (ASCII 'P') defb 06fh, 008h ;0310 Address 0x086f for P command defb 052h ;0312 'R' (ASCII 'R') defb 0ffh, 009h ;0313 Address 0x09ff for R command defb 053h ;0315 'S' (ASCII 'S') defb 03fh, 006h ;0316 Address 0x063f for S command defb 054h ;0318 'T' (ASCII 'T') defb 04fh, 001h ;0319 Address 0x014f for T command defb 057h ;031b 'W' (ASCII 'W') defb 0fah, 009h ;031c Address 0x09fa for W command defb 058h ;031e 'X' (ASCII 'X') defb 00fh, 004h ;031f Address 0x040f for X command defb 03fh ;0321 '?' (ASCII '?') defb 000h ;0322 NULL terminator ; ============================================================================= ; MEMORY COMPARE COMMAND (C command) - Monitor/Debugger Function ; ============================================================================= ; Purpose: Compare two memory regions and display any differences ; Input: User enters hex addresses via console (C start1 end1 start2) ; Example: "C 1000 10FF 2000" compares memory 1000-10FF with 2000-20FF ; Operation: Compares memory at [start1..end1] with memory starting at start2 ; Output: Shows mismatched bytes with both addresses and different values ; Silent operation if regions are identical (no output = blocks match) ; Error handling: Returns to monitor prompt on invalid input or completion ; Used by: Monitor command interpreter for memory debugging and verification ; ============================================================================= l0323h: ; Memory Compare Command Entry Point call sub_0760h ;0323 Parse 3 hex addresses from user input (start1, end1, start2) jp z,l02d9h ;0326 Jump to error handler if hex parsing failed ex de,hl ;0329 DE=start1, HL=start2 (swap for comparison loop setup) l032ah: ; Main Memory Comparison Loop call sub_09a3h ;032a Check for keyboard input (allows user to abort with any key) ld a,(de) ;032d Load byte from first memory region (source) cp (hl) ;032e Compare with byte from second memory region (destination) call nz,sub_0338h ;032f If bytes differ, display the mismatch details inc de ;0332 Move to next byte in first region (source++) cpi ;0333 CP (HL), INC HL, DEC BC - auto-increment second region ret po ;0335 Return when BC=0 (all bytes compared, PO=parity odd/BC=0) jr l032ah ;0336 Continue comparison loop until all bytes checked ; ============================================================================= ; MEMORY MISMATCH DISPLAY HANDLER ; ============================================================================= ; Purpose: Display details when memory comparison finds a difference ; Input: DE=address in first region, HL=address in second region, A=(DE), (HL) differ ; Output: Displays both addresses and their differing byte values ; Format: Shows both addresses with their different values for user analysis ; Example output might be: "1000: 42 2000: 24" (showing the mismatch) ; ============================================================================= sub_0338h: ; Memory Mismatch Display Handler push de ;0338 Save first region address on stack call sub_0346h ;0339 Display first address and its byte value (format: "ADDR: XX") ex (sp),hl ;033c Swap: HL=first addr (from stack), stack=second addr call sub_0346h ;033d Display second address and its byte value (format: "ADDR: YY") call sub_072ah ;0340 Output formatting/newline routine (complete the line) ex de,hl ;0343 Restore proper register order (DE=first, HL=second) pop hl ;0344 Restore second region address from stack ret ;0345 Return to comparison loop ; ============================================================================= ; ADDRESS AND BYTE VALUE DISPLAY ROUTINE ; ============================================================================= ; Purpose: Display an address followed by the byte value at that address ; Input: HL=memory address to display ; Output: Shows "ADDR: XX" format to console ; Used by: Memory compare, memory dump, and other debugging commands ; ============================================================================= sub_0346h: ; Display Address and Byte Value push hl ;0346 Save address ld a,(hl) ;0347 Load byte value from address push af ;0348 Save the byte value call sub_06b8h ;0349 Display the address (HL) in hex ld hl,(011f2h) ;034c Get console output buffer pointer dec hl ;034f Back up one position ld (hl),03dh ;0350 Insert '=' character (0x3D = ASCII '=') pop af ;0352 Restore byte value call sub_06c6h ;0353 Display byte value in hex pop hl ;0356 Restore address ret ;0357 Return call sub_0763h ;0358 jr z,l03a0h ;035b exx ;035d ; ============================================================================= ; MEMORY DUMP/HEX DISPLAY COMMAND - 32 Bytes per Screen ; ============================================================================= ; Purpose: Display memory contents in hex dump format (D command) ; Input: Starting address in HL' (alternate register set) ; Output format: XXXX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX *................* ; Where: XXXX = 4-digit hex address, XX = hex bytes, * = ASCII representation ; Block size: 16 bytes per line, 2 lines = 32 bytes total per screen ; User can press any key to abort display and return to monitor ; ============================================================================= l035eh: ; Memory Dump Command Entry Point call sub_09a3h ;035e Check for keyboard input/break (allows user abort) ld hl,01104h ;0361 Point to display buffer start (console buffer workspace) ld de,01105h ;0364 Point to buffer start + 1 (for block fill operation) ld bc,00049h ;0367 Set count = 73 bytes to clear (full display line + margin) ld (hl),020h ;036a Put space character (0x20) in first position of buffer ldir ;036c Fill entire buffer with spaces (clear display workspace) ld b,010h ;036e Set counter for 16 bytes per line (standard hex dump width) ld hl,01139h ;0370 Point to ASCII display area in buffer (right side of display) ld (hl),02ah ;0373 Put '*' character as left ASCII area separator inc hl ;0375 Move to first ASCII character position exx ;0376 Switch to alternate register set (HL'=current memory address) call sub_06b8h ;0377 Display 4-digit hex address at line start (XXXX format) l037ah: ; Main byte display loop (16 bytes per line) ld a,(hl) ;037a Load byte from current memory address exx ;037b Switch to buffer registers (for ASCII display area) ld (hl),a ;037c Store byte in ASCII display area (right side preview) cp 020h ;037d Compare with space character (0x20) jr c,l0385h ;037f If < 0x20 (control character), replace with dot cp 07fh ;0381 Compare with DEL character (0x7F) jr c,l0387h ;0383 If < 0x7F (printable ASCII), keep original character l0385h: ld (hl),02eh ;0385 Replace with '.' for non-printable characters (0x00-0x1F, 0x7F-0xFF) l0387h: inc hl ;0387 Move to next ASCII display position ld (hl),02ah ;0388 Put '*' separator after ASCII character exx ;038a Switch back to memory address registers call sub_06c6h ;038b Display the hex value of current byte (XX format) cpi ;038e Compare and increment HL, decrement BC (built-in loop control) exx ;0390 Switch to buffer registers for ASCII area management inc hl ;0391 Move buffer pointer to next ASCII position jp po,l0727h ;0392 If BC=0 (parity odd=end of block), finish and display line djnz l039ch ;0395 Decrement line counter B, if not 0 continue current line call l0727h ;0397 Display the completed line (16 bytes hex + ASCII representation) jr l035eh ;039a Start next line (display next address block) l039ch: ; Continue current line processing dec hl ;039c Back up buffer pointer (adjust for proper spacing) exx ;039d Switch back to memory address registers jr l037ah ;039e Continue byte processing loop for same line ; ============================================================================= ; MEMORY EXAMINE AND MODIFY COMMAND (M command) ; ============================================================================= ; Purpose: Interactive memory editing - display address, show current value, ; allow user to enter new value, store it, and continue to next address ; Input: HL = starting memory address (parsed from user command like "M 1000") ; Operation: Shows "ADDR: XX" format, waits for user input, stores new value ; User Interface: Enter new hex value to change, press Enter to skip, 'Q' to quit ; Exit: User presses 'Q' to quit and return to monitor prompt ; Example: "1000: 42" - shows address 1000 has value 42, user can change it ; ============================================================================= l03a0h: ; Memory Examine/Modify Entry Point push hl ;03a0 Save current memory address on stack call sub_06b8h ;03a1 Display address in 4-digit hex format (e.g., "1000:") ld a,(hl) ;03a4 Load current byte value from memory at address call sub_0708h ;03a5 Display current value and get user input (hex parser) jr z,l03b0h ;03a8 If no input/Enter pressed, skip to next address pop hl ;03aa Restore memory address from stack ld (hl),a ;03ab Store new value entered by user into memory push hl ;03ac Save address on stack again for next iteration call sub_0662h ;03ad Call verification/display routine (confirm change) l03b0h: ; Next address processing pop hl ;03b0 Restore current address from stack cp 051h ;03b1 Compare input with 'Q' (0x51 = ASCII 'Q' for quit) ret z ;03b3 Return to monitor prompt if user pressed 'Q' inc hl ;03b4 Move to next memory address (auto-increment) jr l03a0h ;03b5 Loop back to examine next byte (continue editing) ; ============================================================================= ; MEMORY FILL COMMAND (F command) - Fill Memory Block with Pattern Byte ; ============================================================================= ; Purpose: Fill a memory region with a specified byte value using efficient block copy ; Input: User enters "F START END VALUE" - three hex parameters on command line ; Operation: Fills memory from START to END (inclusive) with VALUE byte ; Example: "F 1000 10FF 42" fills addresses 1000-10FF with 0x42 (256 bytes) ; Special case: "FO" prefix jumps to different command handler (File Operations?) ; Technique: Uses single byte + LDIR for efficient bulk memory fill ; ============================================================================= l03b7h: ; Memory Fill Command Entry Point call sub_065eh ;03b7 Get next command character from input buffer (after 'F') cp 04fh ;03ba Compare with 'O' (0x4F = ASCII 'O') jp z,l0a74h ;03bc If 'O', jump to File Operations handler (FO command) call sub_0760h ;03bf Parse three hex parameters: start addr→DE, end addr→HL, value→A and a ;03c2 Clear carry flag for subtraction (prepare SBC calculation) ld (de),a ;03c3 Store fill value at start address (seeds the pattern) sbc hl,de ;03c4 Calculate length = end address - start address ret z ;03c6 Return if length is zero (start=end, only one byte filled) ld b,h ;03c7 Move length to BC register pair (16-bit byte count) ld c,l ;03c8 BC = number of bytes remaining to fill ld h,d ;03c9 HL = start address (source for propagating pattern) ld l,e ;03ca Copy DE (start) to HL inc de ;03cb DE = start address + 1 (destination for pattern copy) ldir ;03cc Fill memory: copy (HL) to (DE), repeat BC times ret ;03ce Return to monitor (entire memory region now filled) ; ============================================================================= ; DEBUG/DISPLAY PARAMETER COMMAND (I command) - Configure Display Settings ; ============================================================================= ; Purpose: Configure debugging display parameters, modes, or formatting options ; Input: User enters "I XXXX" where XXXX is hex value for display parameter ; Storage: Parameter value stored at memory address 0x11D6 ; Special case: "II" command jumps to specialized display handler at 0x0A86 ; Use cases: Sets display width, format modes, or debugging visualization options ; Examples: "I 10" might set 16-byte display width, "I 01" might enable trace mode ; ============================================================================= l03cfh: ; I Command (Debug/Display Parameter) Entry Point call sub_065eh ;03cf Get next command character from input buffer (check for "II") cp 044h ;03d2 Compare with 'I' (0x49 = ASCII 'I' for "II" command variant) jp z,l0a86h ;03d4 If second 'I', jump to specialized display command handler ld a,(011d6h) ;03d7 Load current debug display parameter from memory (0x11D6) call sub_0708h ;03da Get hex input from user (new parameter value for I command) ret z ;03dd Return if no input provided (display current parameter value) ld (011d6h),a ;03de Store new debug display parameter at 0x11D6 ret ;03e1 Return to monitor (I command parameter updated) ; ============================================================================= ; BREAKPOINT/EXECUTION COUNTER COMMAND - Program Execution Control ; ============================================================================= ; Purpose: Set up execution counter for controlled program stepping/tracing ; Input: User enters hex counter value (number of instructions to execute) ; Operation: Sets up debugging counter for single-step or limited execution ; Use case: "B 100" might execute 256 instructions then break back to monitor ; ============================================================================= l03e2h: ; Breakpoint/Counter Command Entry Point call sub_03f7h ;03e2 Call setup/initialization routine (clear counters?) call sub_0680h ;03e5 Parse hex input from user (execution count) ret z ;03e8 Return if no valid input provided (show current count?) call sub_0405h ;03e9 Process the counter value (setup execution limit) sub_03ech: ; Counter Processing Subroutine - EXECUTION STEP COUNTER call sub_0680h ;03ec Parse hex input from user (step count parameter) jr nz,l03f3h ;03ef If valid hex input provided, store it as step count ld a,001h ;03f1 Default step count = 1 (single step if no input) l03f3h: ld (011d0h),a ;03f3 Store step counter at 0x11D0 (execution step limit) ret ;03f6 Return to single-step execution controller ; ============================================================================= ; BREAKPOINT RESTORATION ROUTINE ; ============================================================================= ; Purpose: Restore original instruction that was replaced by breakpoint ; Operation: Reads saved instruction byte and restores it to memory ; Used by: Breakpoint system to clean up after break execution ; ============================================================================= sub_03f7h: ; Breakpoint Restoration ld hl,(011f0h) ;03f7 Load breakpoint address from memory ld a,(011cfh) ;03fa Load saved original instruction byte ld (hl),a ;03fd Restore original instruction at breakpoint ld hl,l0000h ;03fe Clear breakpoint address (set to 0000) ld (011f0h),hl ;0401 Store cleared address (no active breakpoint) l0404h: ret ;0404 Return ; ============================================================================= ; BREAKPOINT INSTALLATION ROUTINE ; ============================================================================= ; Purpose: Install breakpoint by replacing instruction with 0xFF ; Operation: Saves original instruction and replaces it with break opcode ; Input: HL = address where breakpoint should be set ; Memory: 011cfh = saved original instruction, 011f0h = breakpoint address ; ============================================================================= sub_0405h: ; Breakpoint Installation ld a,(hl) ;0405 Load original instruction from target address ld (011cfh),a ;0406 Save original instruction byte ld (hl),0ffh ;0409 Replace with breakpoint opcode (0xFF = RST 38H) ld (011f0h),hl ;040b Store breakpoint address for later restoration ret ;040e Return ; ============================================================================= ; INSTRUCTION ANALYSIS AND BREAKPOINT PLACEMENT ; ============================================================================= ; Purpose: Analyze instruction stream and set appropriate breakpoints ; Used by: Single-step debugging and program flow analysis ; ============================================================================= l040fh: ; Instruction Analysis Entry Point call sub_03f7h ;040f Restore any existing breakpoint first ld hl,(011eah) ;0412 Load current execution address call sub_0425h ;0415 Analyze instruction at current address jp nc,l049fh ;0418 If NOT special instruction, jump to normal execution path ld e,a ;041b Move instruction length to E register ld d,000h ;041c Clear D register (DE = instruction length in bytes) add hl,de ;041e Calculate next instruction address (current + length) call sub_0405h ;041f Set breakpoint at NEXT instruction (step-over mode) jp l044ah ;0422 Jump to execution setup and run until breakpoint hit ; ============================================================================= ; Z80 INSTRUCTION DECODER - Analyzes instruction types for debugging ; ============================================================================= ; Purpose: Decode Z80 instructions to determine their type and length ; Input: HL points to instruction to analyze ; Output: Carry set if special instruction, A = instruction length ; Special instructions: CALL, RET, conditional jumps, block operations ; ============================================================================= sub_0425h: ; Z80 Instruction Decoder ld a,(hl) ;0425 Load instruction opcode cp 0edh ;0426 Check for ED prefix (extended instructions) jr z,l0437h ;0428 If ED prefix, handle extended instructions cp 0cdh ;042a Check for CALL instruction (0xCD) jr z,l0433h ;042c If CALL, return length 3 and 0c4h ;042e Mask bits to check instruction pattern xor 0c4h ;0430 Check for conditional CALL pattern (11xxx100) ret nz ;0432 Return if not special instruction (carry clear) l0433h: ; CALL instruction handler ld a,003h ;0433 CALL instructions are 3 bytes long scf ;0435 Set carry flag (special instruction detected) ret ;0436 Return with instruction length l0437h: ; Extended instruction handler (ED prefix) inc hl ;0437 Move to second byte of ED instruction ld a,(hl) ;0438 Load second opcode byte and 0f0h ;0439 Mask upper nibble xor 0b0h ;043b Check for block operation pattern (10110xxx) ret nz ;043d Return if not block operation inc a ;043e A = 1 (ED block instructions are 2 bytes) scf ;043f Set carry flag (special instruction detected) ret ;0440 Return with instruction length ; ============================================================================= ; JUMP/EXECUTE COMMAND (J command) - Execute program from specified address ; ============================================================================= ; Purpose: Start program execution from user-specified address (same as G command) ; Input: User provides "J XXXX" where XXXX is hex address to execute ; Operation: Sets up execution environment and transfers control to user program ; Note: J command shares the same implementation as G (Go) command ; ============================================================================= l0441h: ; J Command (Jump/Execute) Entry Point call sub_0680h ;0441 Parse hex address from user input (e.g., "J 1000") jp z,l02d9h ;0444 Jump to error handler if invalid address entered ld (011eah),hl ;0447 Store execution start address in system variable ; ============================================================================= ; PROGRAM EXECUTION CONTROLLER (shared by G and J commands) ; ============================================================================= ; Purpose: Set up CPU state and execute user program with debugging support ; Features: Interrupt handling, breakpoint detection, register restoration ; Used by: Both G (Go) and J (Jump) commands use this same execution logic ; ============================================================================= l044ah: ; Program Execution Setup ld a,(011d7h) ;044a Load interrupt vector high byte from system config ld i,a ;044d Set Z80 interrupt vector register (for IM2 mode) ld de,(011eah) ;044f Load target execution address from user input (G/J command) ld hl,(011f0h) ;0453 Load current breakpoint address from active breakpoint and a ;0456 Clear carry flag for 16-bit address comparison sbc hl,de ;0457 Compare: is breakpoint already at execution start address? jr z,l0472h ;0459 If breakpoint at execution address, handle as special case ld hl,(011d6h) ;045b Load debug control parameters (interrupt/trace modes) ld a,h ;045e Get high byte of debug params for interrupt vector ld i,a ;045f Set interrupt vector register for user program context di ;0461 Disable interrupts during critical register setup phase bit 0,l ;0462 Check debug control bit 0 (interrupt enable flag for user) jr z,l0467h ;0464 If bit 0 clear, keep interrupts disabled during execution ei ;0466 Re-enable interrupts if user program expects them enabled ;============================================================================== ; USER PROGRAM EXECUTION CONTROLLER (0x0467-0x0471) ;============================================================================== ; Purpose: Execute user program with full debugger support and state management ; Entry: l0467h - Called after breakpoint setup or direct execution request ; Operation: Restore registers → Execute user code → Handle return → Process results ;============================================================================== l0467h: ; Execute User Program Entry Point call sub_079bh ;0467 CRITICAL: Restore all registers and execute user code ld hl,(011eah) ;046a Reload execution address from save area (post-execution) push hl ;046d Save execution address on stack for debug analysis ld hl,(011d4h) ;046e Load debug parameters/status from execution control ret ;0471 Return to calling debugger routine with status ;============================================================================== ; ERROR HANDLER AND MEMORY RESTORATION (0x0472-0x0478) ;============================================================================== ; Purpose: Handle execution errors and restore memory state after breakpoints ; Used by: Debugger cleanup routines and breakpoint removal system ;============================================================================== l0472h: ; Error Handler Entry Point ld hl,l07efh ;0472 Load address for execution/error handler routine l0475h: ; Memory restoration entry point (breakpoint cleanup) ld a,(011cfh) ;0475 Load saved byte value from backup storage location ld (de),a ;0478 Restore original byte at target address (remove breakpoint) ;============================================================================== ; BREAKPOINT INSTALLATION WITH MEMORY PAGING (0x0479-0x049D) ;============================================================================== ; Purpose: Install software breakpoint in paged memory with full state management ; Features: Memory paging control, interrupt management, state backup/restoration ; Operation: Enables paging → Selects memory page → Plants breakpoint → Saves state ; ; Memory Paging Sequence: ; 1. Disable interrupts for atomic operation ; 2. Configure interrupt mode 2 with vector table at 0x1300 ; 3. Enable 64KB memory card paging system via port 0x000 ; 4. Select target memory page via dual-write to port 0x003 ; 5. Install breakpoint instruction and backup original data ; ; Port Operations: ; • PORT 0x000 (0x20): Memory management control - enables bank switching ; • PORT 0x003 (0x87, 0x01): Page selection - first 0x87 (page 7 + control), then 0x01 (page 1) ; ; State Management: ; • Backs up original instruction before planting 0xFB (EI) breakpoint ; • Stores breakpoint location and original data for safe restoration ; • Integrates with debugger's execution control and single-step system ;============================================================================== l0479h: ; Breakpoint Installation Entry Point dec de ;0479 Decrement target address by 1 (align to exact breakpoint location) di ;047a Disable interrupts for atomic breakpoint installation ld a,013h ;047b Set interrupt vector base 0x13 (points to table at 0x1300) ld i,a ;047d Load interrupt vector register (prepare for IM2 mode) ld a,020h ;047f Memory control: 0x20 = Enable 64KB paging system out (000h),a ;0481 PORT 0x000: Memory management control (activate paging) im 2 ;0483 Set interrupt mode 2 (vectored interrupts via table) ld a,087h ;0485 Page select: 0x87 = Page 7 + control bits active out (003h),a ;0487 PORT 0x003: Page selection register (first selection) ld a,001h ;0489 Page select: 0x01 = Select memory page 1 for breakpoint out (003h),a ;048b PORT 0x003: Page selection register (second selection) ld (01326h),hl ;048d Store HL at 0x1326 (breakpoint address for paging system) ex de,hl ;0490 Exchange: HL=decremented target addr, DE=original addr ld (011d1h),hl ;0491 Store active breakpoint address at 0x11D1 (current BP) ld a,(hl) ;0494 Load original instruction byte from breakpoint location ld (011d3h),a ;0495 Store original byte at 0x11D3 (backup for restoration) ld (hl),0fbh ;0498 Plant breakpoint: 0xFB = EI instruction (interrupt enable) ld (011eah),hl ;049a Store breakpoint address at 0x11EA (execution target) jr l0467h ;049d Jump to execution preparation (complete breakpoint cycle) ;============================================================================== ; NORMAL INSTRUCTION EXECUTION PATH (0x049F) - NON-SPECIAL INSTRUCTIONS ;============================================================================== ; Purpose: Handle execution of normal instructions (not CALL/RET/conditional jumps) ; Entry: Jumped to from 0x0418 when instruction decoder finds standard instruction ; Operation: Set up single-step debugging environment for normal instruction execution ; Features: Console buffer setup, memory management, step-by-step execution control ;============================================================================== l049fh: ; Normal Instruction Execution Entry Point call sub_05a5h ;049f Initialize console buffer system (prepare for single-step I/O) call sub_03ech ;04a2 Process execution counter/step parameters l04a5h: ; Single-Step Execution Loop Controller ld hl,(011d6h) ;04a5 Load debug control parameters from system settings ld (011eeh),hl ;04a8 Save debug parameters for restoration after execution ld de,(011eah) ;04ab Load current execution address (where to execute next) ld hl,(011f0h) ;04af Load active breakpoint address from system and a ;04b2 Clear carry flag for 16-bit address comparison sbc hl,de ;04b3 Compare: is execution address same as breakpoint address? ld hl,l04bch ;04b5 Load address of breakpoint handler routine jr z,l0475h ;04b8 If at breakpoint, jump to memory restoration routine jr l0479h ;04ba Otherwise, jump to breakpoint installation routine l04bch: ld (011d4h),hl ;04bc Store execution return address in debug control block pop hl ;04bf Restore HL register from stack (return to caller state) ld (011ech),sp ;04c0 Save current stack pointer for later restoration ld sp,01400h ;04c4 Set up temporary debug stack at 0x1400 call sub_0770h ;04c7 Call system state preservation routine call sub_04ebh ;04ca Call memory paging restore routine ld hl,l04d3h ;04cd Load address of execution continuation point push hl ;04d0 Push continuation address onto stack reti ;04d1 Return from interrupt (execute user instruction) l04d3h: ld hl,(011eeh) ;04d3 Restore debug control parameters from backup ld (011d6h),hl ;04d6 Store restored parameters back to system settings call sub_0582h ;04d9 Call post-execution cleanup routine ld hl,011d0h ;04dc Point to single-step counter location dec (hl) ;04df Decrement step counter (one instruction executed) jr nz,l04a5h ;04e0 If more steps remaining, continue execution loop inc (hl) ;04e2 Reset step counter to 1 (prepare for next command) call sub_080dh ;04e3 Call debugger command processing routine jp nz,l02c9h ;04e6 If command processed, jump to main command loop jr l04a5h ;04e9 Otherwise, continue single-step execution ;============================================================================== ; MEMORY PAGING RESTORE ROUTINE (0x04EB) ;============================================================================== ; Purpose: Restore default memory page and clean up paging state ; Called during system shutdown or page switching operations ; ; Operation: ; - Switches back to page 3 (likely default/system page) ; - Restores original memory contents from backup ; - Cleans up paging state for safe transition ;============================================================================== sub_04ebh: ld a,003h ;04eb ; Load page 3 (default/system page) out (003h),a ;04ed ; PORT 0x003: Switch to page 3 ld hl,(011d1h) ;04ef ; Load backup memory address ld a,(011d3h) ;04f2 ; Load original byte value ld (hl),a ;04f5 ; Restore original memory contents ld hl,(011f0h) ;04f6 ; Load cleanup address ld (hl),0ffh ;04f9 ; Mark memory as restored/available ret ;04fb ; Return to caller call sub_0760h ;04fc jp z,l02d9h ;04ff push hl ;0502 and a ;0503 sbc hl,de ;0504 pop hl ;0506 l0507h: jr c,l050ch ;0507 l0509h: ldir ;0509 ret ;050b l050ch: add hl,bc ;050c dec hl ;050d ex de,hl ;050e add hl,bc ;050f dec hl ;0510 ex de,hl ;0511 lddr ;0512 ret ;0514 call sub_0662h ;0515 jr z,l057fh ;0518 ld d,a ;051a call sub_065eh ;051b jr nz,l0522h ;051e ld a,020h ;0520 l0522h: ld e,a ;0522 call sub_05cch ;0523 dec hl ;0526 dec hl ;0527 jp nz,l02d9h ;0528 l052bh: ld de,01104h ;052b ldi ;052e ldi ;0530 push hl ;0532 ex de,hl ;0533 ld (hl),020h ;0534 inc hl ;0536 ld (011f2h),hl ;0537 ld hl,l060eh ;053a or a ;053d ex de,hl ;053e sbc hl,de ;053f ld e,(ix+000h) ;0541 ld d,(ix+001h) ;0544 jr nc,l056ah ;0547 ld a,(de) ;0549 push de ;054a call sub_0708h ;054b pop de ;054e jr z,l0555h ;054f ld (de),a ;0551 l0552h: call sub_0662h ;0552 l0555h: cp 051h ;0555 pop hl ;0557 ret z ;0558 inc ix ;0559 inc ix ;055b ex de,hl ;055d push hl ;055e ld hl,l0615h ;055f or a ;0562 sbc hl,de ;0563 pop hl ;0565 ex de,hl ;0566 jr nz,l052bh ;0567 ret ;0569 l056ah: ld a,(de) ;056a ld l,a ;056b inc de ;056c ld a,(de) ;056d ld h,a ;056e call sub_06b8h ;056f push de ;0572 call sub_070bh ;0573 pop de ;0576 jr z,l0555h ;0577 ex de,hl ;0579 ld (hl),d ;057a dec hl ;057b ld (hl),e ;057c jr l0552h ;057d l057fh: call sub_05a5h ;057f sub_0582h: ld b,011h ;0582 ld hl,l0615h ;0584 l0587h: ld e,(hl) ;0587 inc hl ;0588 ld d,(hl) ;0589 inc hl ;058a ld a,(de) ;058b call sub_06c6h ;058c djnz l0587h ;058f ld b,004h ;0591 l0593h: ld e,(hl) ;0593 inc hl ;0594 ld d,(hl) ;0595 inc hl ;0596 ex de,hl ;0597 ld a,(hl) ;0598 inc hl ;0599 ld h,(hl) ;059a ld l,a ;059b call sub_06b8h ;059c ex de,hl ;059f djnz l0593h ;05a0 l05a2h: jp sub_072ah ;05a2 ;============================================================================== ; CONSOLE BUFFER INITIALIZATION (sub_05a5h) - REGISTER DISPLAY SETUP ;============================================================================== ; Purpose: Initialize console buffer system with register name templates ; Operation: Copy register name strings from ROM table to RAM buffer area ; Used by: Single-step debugging to prepare register display output ; Buffer: 0x1104 = console buffer start, filled with register names for display ;============================================================================== sub_05a5h: ; Console Buffer Initialization Entry Point ld de,01104h ;05a5 DE = console buffer start address (0x1104) ld hl,l05ebh ;05a8 HL = register name table in ROM (0x05EB - register names) ld bc,011ffh ;05ab BC = loop count (B=0x01, C=0xFF - copy parameters) ld a,020h ;05ae A = 0x20 (space character for formatting) l05b0h: ; Register Name Copy Loop ldi ;05b0 Copy first character from register table to buffer ldi ;05b2 Copy second character from register table to buffer ld (de),a ;05b4 Store space character (0x20) after register name inc de ;05b5 Advance buffer pointer past space djnz l05b0h ;05b6 Loop until all register names copied (B times) ld b,004h ;05b8 Set loop counter for additional buffer setup (4 iterations) l05bah: ; Additional Buffer Formatting Loop ld (de),a ;05ba Store space character in buffer inc de ;05bb Advance buffer pointer ldi ;05bc Copy character from register table to buffer ldi ;05be Copy second character from register table to buffer ld (de),a ;05c0 Store space character after register name inc de ;05c1 Advance buffer pointer ld (de),a ;05c2 Store another space character (double spacing) inc de ;05c3 Advance buffer pointer djnz l05bah ;05c4 Loop for remaining register names (4 times) ld (011f2h),de ;05c6 Store final buffer pointer at 0x11F2 (buffer end) jr l05a2h ;05ca Jump to buffer completion routine sub_05cch: ld ix,l0615h ;05cc ld bc,l002ah ;05d0 ld hl,l05ebh ;05d3 l05d6h: ld a,d ;05d6 cpi ;05d7 jr z,l05e5h ;05d9 xor a ;05db cpi ;05dc l05deh: ret po ;05de inc ix ;05df inc ix ;05e1 jr l05d6h ;05e3 l05e5h: ld a,e ;05e5 cpi ;05e6 ret z ;05e8 jr l05deh ;05e9 ;============================================================================== ; Z80 REGISTER NAME TABLE (0x05EB+) ; Purpose: ASCII string table of Z80 register names for display/debugging ; Format: Space-separated register names, single quotes for alternate registers ; Content: "A B C D E F H L I A'B'C'D'E'F'H'L'IXI..." ;============================================================================== ;============================================================================== ; Z80 REGISTER NAME AND ADDRESS LOOKUP TABLE (0x05EB-0x63D) ; Purpose: Complete register name table with corresponding addresses for debugger/monitor ; Format: ASCII register names followed by address lookup table ;============================================================================== register_names_05ebh: ; Register name strings (space-separated) db "A B C D E F H L I A'B'C'D'E'F'H'L'IXI" ;05eb-060f db "YPCSP" ;0610-0614 (IY, PC, SP registers) ; Address lookup table (each entry is 0x11 followed by address) db 0xD9, 0x11, 0xDB, 0x11, 0xDA, 0x11, 0xDD, 0x11 ;0615-061c db 0xDC, 0x11, 0xD8, 0x11, 0xD5, 0x11, 0xD4, 0x11 ;061d-0624 db 0xD7, 0x11, 0xDF, 0x11, 0xE1, 0x11, 0xE0, 0x11 ;0625-062c db 0xE3, 0x11, 0xE2, 0x11, 0xDE, 0x11, 0xE5, 0x11 ;062d-0634 db 0xE4, 0x11, 0xE6, 0x11, 0xE8, 0x11, 0xEA, 0x11 ;0635-063c db 0xEC, 0x11 ;063d-063e ;============================================================================== ; HEX INPUT SEQUENCE (0x063F) ;============================================================================== ; Purpose: Parse two hexadecimal values from user input ; Typical use: Address and data entry for memory operations ; Example: User types "1000 FF" to store 0xFF at address 0x1000 ;============================================================================== sub_063fh: call sub_0680h ;063f ; Parse first hex string (e.g., address) push hl ;0642 ; Save first parsed value on stack call sub_0680h ;0643 ; Parse second hex string (e.g., data) pop hl ;0646 ; Restore first value to HL ret z ;0647 ; Return if second parse failed ld (hl),a ;0648 ; Store second value (data) at first value (address) inc hl ;0649 ; Increment to next address jr $-8 ;064a ; Loop back to continue operation sub_064ch: ex (sp),hl ;064c ld b,(hl) ;064d l064eh: inc hl ;064e cp (hl) ;064f inc hl ;0650 ld e,(hl) ;0651 inc hl ;0652 ld d,(hl) ;0653 jr nz,l0659h ;0654 ex de,hl ;0656 ex (sp),hl ;0657 ret ;0658 l0659h: djnz l064eh ;0659 jp l02d9h ;065b sub_065eh: inc hl ;065e ld a,(hl) ;065f jr l0677h ;0660 ; ============================================================================= ; INPUT BUFFER SCANNER - Skip Spaces and Process Next Character ; ============================================================================= ; Purpose: Scan input buffer, skip spaces, and return next non-space character ; Input: (011f4h) points to current position in input buffer ; Output: A = next non-space character, HL updated to new position ; Used by: Memory modify command to parse user input after displaying value ; ============================================================================= sub_0662h: ; Input Buffer Scanner ld hl,(011f4h) ;0662 Load current input buffer pointer l0665h: ; Space-skipping loop ld a,(hl) ;0665 Load character from buffer cp 00dh ;0666 Check for CR (end of line) jr z,l0674h ;0668 If CR, finish and update pointer cp 020h ;066a Check for space character l066ch: ; Continue scanning loop inc hl ;066c Move to next character jr nz,l0665h ;066d If not space, check if still space at new position ld a,(hl) ;066f Load next character cp 020h ;0670 Check if it's also a space jr z,l066ch ;0672 If space, continue skipping spaces l0674h: ; Update buffer pointer and process character ld (011f4h),hl ;0674 Store updated buffer pointer l0677h: ; Character processing bit 6,a ;0677 Check bit 6 (lowercase letter detection) jr z,l067dh ;0679 If not set, skip case conversion res 5,a ;067b Convert lowercase to uppercase (clear bit 5) l067dh: ; Final character check cp 00dh ;067d Compare with CR (carriage return) ret ;067f Return with flags set ;============================================================================== ; HEXADECIMAL STRING PARSER (0x0680) ;============================================================================== ; Purpose: Convert ASCII hexadecimal string to binary value ; Input: DE points to ASCII hex string (e.g. "1A2F") ; Output: HL contains parsed binary value, A contains last character processed ; ; Supported formats: ; - Digits 0-9 (ASCII 0x30-0x39) ; - Letters A-F (ASCII 0x41-0x46, case insensitive) ; - Automatically converts lowercase a-f to uppercase A-F ; ; Error handling: Invalid characters cause jump to error handler at l02d9h ; ; Algorithm: ; 1. Initialize result to 0 ; 2. For each character: validate, convert, pack into result ; 3. Use RLD instruction for efficient 4-bit nibble packing ; 4. Continue until non-hex character found ;============================================================================== sub_0680h: ld hl,l0000h ;0680 ; Initialize result to 0 push hl ;0683 ; Save initial value on stack add hl,sp ;0684 ; HL = stack pointer (for result storage) ex de,hl ;0685 ; DE = stack pointer, HL = string pointer call sub_0662h ;0686 ; Get next character from input ex de,hl ;0689 ; Restore: HL = stack pointer, DE = string pointer jr nz,l068fh ;068a ; If character available, process it l068ch: pop hl ;068c ; Restore result from stack ld a,l ;068d ; Return low byte in A ret ;068e ; Return with parsed value l068fh: cp 030h ;068f ; Compare with '0' (0x30) jp c,l02d9h ;0691 ; If < '0', invalid hex character - error l0694h: cp 041h ;0694 ; Compare with 'A' (0x41) jr c,l069ah ;0696 ; If < 'A', must be digit 0-9, go convert res 5,a ;0698 ; Convert lowercase to uppercase (clear bit 5) l069ah: cp 03ah ;069a ; Compare with ':' (0x3A, one past '9') jr c,l06aah ;069c ; If < ':', it's digit 0-9, go pack cp 041h ;069e ; Compare with 'A' (0x41) jp c,l02d9h ;06a0 ; If between ':' and 'A', invalid - error cp 047h ;06a3 ; Compare with 'G' (0x47, one past 'F') jp nc,l02d9h ;06a5 ; If >= 'G', invalid hex letter - error sub 007h ;06a8 ; Convert A-F to 10-15 (subtract 7) l06aah: rld ;06aa ; Rotate left digit: pack nibble into (HL) inc hl ;06ac ; Point to next byte for multi-byte values rld ;06ad ; Pack into high nibble of next byte dec hl ;06af ; Return to original position inc de ;06b0 ; Point to next character in input string ld a,(de) ;06b1 ; Load next character cp 030h ;06b2 ; Check if >= '0' jr nc,l0694h ;06b4 ; If valid hex character, continue parsing jr l068ch ;06b6 ; Otherwise, end parsing and return result ;============================================================================== ; 16-BIT HEX ADDRESS FORMATTER (0x06B8) ;============================================================================== ; Purpose: Convert 16-bit value in HL to 4-digit hex string and store in output buffer ; Used extensively throughout the monitor for displaying memory addresses, ; breakpoint locations, and register values in XXXX format. ; ; Input: HL = 16-bit value to format (e.g., memory address) ; Output: 4-character hex string written to console buffer at (0x011F2) ; Followed by a space character for proper formatting ; Buffer: Updates 0x011F2 pointer to reflect new buffer position ; ; Format: Converts 0x1234 → "1234 " (4 hex digits + space) ; Usage: Called by memory display, breakpoint display, register dump routines ; ; Technical Details: ; • Processes high byte (H) first, then low byte (L) ; • Each byte converted to 2 hex characters using sub_06c6h ; • Automatically adds space separator after hex digits ; • Updates buffer pointer for subsequent output operations ;============================================================================== sub_06b8h: ld a,h ;06b8 ; Load high byte of 16-bit value call sub_06c6h ;06b9 ; Convert high byte to 2 hex characters push hl ;06bc ; Save original 16-bit value ld hl,(011f2h) ;06bd ; Load current console buffer pointer dec hl ;06c0 ; Back up one position (preparation for space) ld (011f2h),hl ;06c1 ; Update buffer pointer pop hl ;06c4 ; Restore original 16-bit value ld a,l ;06c5 ; Load low byte of 16-bit value ;============================================================================== ; SINGLE BYTE HEX FORMATTER (0x06C6) ;============================================================================== ; Purpose: Convert single byte to 2-digit hex string and store in output buffer ; Input: A = byte value to convert (0x00-0xFF) ; Output: 2-character hex string written to buffer, followed by space ; Used by: 16-bit formatter above, and other hex display routines ;============================================================================== sub_06c6h: push hl ;06c6 ; Save registers ld hl,(011f2h) ;06c7 ; Load current console buffer pointer call sub_06d6h ;06ca ; Convert byte to 2 hex characters at buffer inc hl ;06cd ; Move past the 2 hex characters ld (hl),020h ;06ce ; Store space character (0x20) for separation inc hl ;06d0 ; Move past space character ld (011f2h),hl ;06d1 ; Update buffer pointer to new position pop hl ;06d4 ; Restore registers ret ;06d5 ;============================================================================== ; BYTE TO HEX DIGIT CONVERTER (0x06D6) ;============================================================================== ; Purpose: Convert single byte to 2 ASCII hex characters ; Input: A = byte value, HL = buffer location ; Output: 2 hex characters stored at HL and HL+1 ; Method: Splits byte into high/low nibbles, converts each to ASCII hex ;============================================================================== sub_06d6h: push af ;06d6 ; Save original byte value rra ;06d7 ; Rotate right 4 times to get high nibble rra ;06d8 ; in low 4 bits rra ;06d9 rra ;06da call sub_06e0h ;06db ; Convert high nibble to hex character inc hl ;06de ; Move to next buffer position pop af ;06df ; Restore original byte value ;============================================================================== ; NIBBLE TO HEX CHARACTER CONVERTER (0x06E0) ;============================================================================== ; Purpose: Convert single nibble (0-15) to ASCII hex character ; Input: A = nibble value (0-15), HL = buffer location ; Output: ASCII hex character ('0'-'9', 'A'-'F') stored at (HL) ;============================================================================== sub_06e0h: and 00fh ;06e0 ; Mask to get only low 4 bits (nibble) cp 00ah ;06e2 ; Compare with 10 jr c,l06e8h ;06e4 ; If < 10, convert to '0'-'9' add a,007h ;06e6 ; If >= 10, add 7 to convert to 'A'-'F' l06e8h: add a,030h ;06e8 ; Add ASCII '0' offset to get final character ld (hl),a ;06ea ; Store ASCII hex character in buffer ret ;06eb ; Return ;============================================================================== ; CONSOLE OUTPUT FORMATTER & UTILITIES (0x06EC-0x076F) ;============================================================================== ; Collection of routines for formatting and outputting data to the console ; with proper control characters and formatting. ;============================================================================== ;============================================================================== ; STRING DISPLAY WITH CONTROL FORMATTING (0x06EC) ;============================================================================== ; Purpose: Display string from HL with proper control character formatting ; Adds ETX (0x02) prefix and EOT (0x03) suffix around displayed text ; Used for formatted console output with control framing ;============================================================================== l06ech: inc hl ;06ec ; Move to start of string data ld c,002h ;06ed ; Load ETX control character (Start of Text) call sub_0111h ;06ef ; Send ETX to serial port l06f2h: ld a,(hl) ;06f2 ; Load next character from string cp 020h ;06f3 ; Check if space character (end marker) jr z,l0702h ;06f5 ; If space, end string output cp 00dh ;06f7 ; Check if carriage return (end marker) jr z,l0702h ;06f9 ; If CR, end string output ld c,a ;06fb ; Load character into C for output call sub_0111h ;06fc ; Send character to serial port inc hl ;06ff ; Move to next character jr l06f2h ;0700 ; Continue until end marker found l0702h: ld c,003h ;0702 ; Load EOT control character (End of Text) call sub_0111h ;0704 ; Send EOT to serial port ret ;0707 ; Return ;============================================================================== ; HEX BYTE DISPLAY WITH INPUT PROMPT (0x0708) ;============================================================================== ; Purpose: Display byte value and prompt for user input ; Used by memory examination commands for interactive editing ;============================================================================== sub_0708h: call sub_06c6h ;0708 ; Format and display byte as 2-digit hex + space ;============================================================================== ; CONSOLE OUTPUT FLUSH AND INPUT PROMPT (0x070B) ;============================================================================== ; Purpose: Flush current output buffer and prompt for user input ; Sets up interactive prompt with space character and waits for input ;============================================================================== sub_070bh: call sub_0745h ;070b ; Flush output buffer to console ld a,020h ;070e ; Load space character ld (011f6h),a ;0710 ; Set prompt character to space call sub_080dh ;0713 ; Get character from user input cp 051h ;0716 ; Check if 'Q' (quit command) ret z ;0718 ; Return if user wants to quit ld hl,01168h ;0719 ; Load input buffer address ld (hl),020h ;071c ; Initialize buffer with space ld (011f4h),hl ;071e ; Set input buffer pointer push de ;0721 ; Save DE register call sub_0680h ;0722 ; Parse hex input from user pop de ;0725 ; Restore DE register ret ;0726 ; Return ;============================================================================== ; OUTPUT BUFFER MANAGEMENT ROUTINES (0x0727-0x076F) ;============================================================================== ; Purpose: Handle console output buffer operations including line formatting, ; buffer flushing, and register preservation during I/O operations ;============================================================================== ;============================================================================== ; SET OUTPUT BUFFER POINTER (0x0727) ;============================================================================== l0727h: ld (011f2h),hl ;0727 ; Store HL as new output buffer pointer ;============================================================================== ; FLUSH OUTPUT WITH NEWLINE (0x072A) ;============================================================================== ; Purpose: Add CR/LF to output buffer and flush to console ; Preserves all registers during output operation ;============================================================================== sub_072ah: push hl ;072a ; Save all registers push de ;072b push bc ;072c ld hl,(011f2h) ;072d ; Load current buffer pointer ld (hl),00dh ;0730 ; Add carriage return inc hl ;0732 ; Move to next position ld (hl),00ah ;0733 ; Add line feed inc hl ;0735 ; Move to next position l0736h: ld (hl),000h ;0736 ; Add null terminator ld hl,01104h ;0738 ; Reset buffer pointer to start ld (011f2h),hl ;073b ; Update buffer pointer call l00fdh ;073e ; Send buffer contents to console pop bc ;0741 ; Restore all registers pop de ;0742 pop hl ;0743 ret ;0744 ; Return ;============================================================================== ; FLUSH OUTPUT WITHOUT NEWLINE (0x0745) ;============================================================================== ; Purpose: Flush current output buffer to console without adding newline ; Used for partial line output and formatting ;============================================================================== sub_0745h: push hl ;0745 ; Save all registers push de ;0746 push bc ;0747 ld hl,(011f2h) ;0748 ; Load current buffer pointer jr l0736h ;074b ; Jump to common flush routine ;============================================================================== ; OUTPUT BUFFER WITH CHARACTER INPUT (0x074D) ;============================================================================== ; Purpose: Flush output buffer and get character input from console ; Returns input character while preserving registers ;============================================================================== sub_074dh: push hl ;074d ; Save registers push de ;074e ld hl,(011f2h) ;074f ; Load current buffer pointer ld (hl),000h ;0752 ; Add null terminator ld hl,01104h ;0754 ; Reset buffer pointer to start ld (011f2h),hl ;0757 ; Update buffer pointer call l0107h ;075a ; Output buffer and get input character pop de ;075d ; Restore registers pop hl ;075e ret ;075f ; Return with input character in A ;============================================================================== ; MULTI-PARAMETER HEX INPUT PARSER (0x0760-0x076F) ;============================================================================== ; Purpose: Parse multiple hexadecimal parameters from user input ; Returns parsed values in HL, DE, and BC registers ;============================================================================== sub_0760h: call sub_0680h ;0760 ; Parse first hex parameter → HL ;============================================================================== ; TWO-PARAMETER HEX INPUT PARSER (0x0763) ;============================================================================== sub_0763h: push hl ;0763 ; Save first parameter call sub_0680h ;0764 ; Parse second hex parameter → HL push hl ;0767 ; Save second parameter call sub_0680h ;0768 ; Parse third hex parameter → HL ld b,h ;076b ; Store third parameter high byte in B ld c,l ;076c ; Store third parameter low byte in C pop hl ;076d ; Restore second parameter to HL pop de ;076e ; Restore first parameter to DE ret ;076f ; Return: DE=1st param, HL=2nd param, BC=3rd param ;============================================================================== ; COMPLETE CPU STATE SAVE ROUTINE (sub_0770h) - CRITICAL SYSTEM COMPONENT ;============================================================================== ; Purpose: Save ALL Z80 CPU registers and set up interrupt environment ; Used by: Interrupt handlers, breakpoint system, system initialization ; Operation: Saves complete CPU state to stack area, sets up IM2 interrupts ; Stack Layout: Creates complete register save area for later restoration ; ; REGISTER SAVE ORDER (pushed to stack at 0x011EC): ; 1. HL (main register pair) ; 2. IY (index register Y) ; 3. IX (index register X) ; 4. HL' (alternate HL) ; 5. DE' (alternate DE) ; 6. BC' (alternate BC) ; 7. AF' (alternate accumulator/flags) ; 8. DE (main register pair) ; 9. BC (main register pair) ; 10. AF (main accumulator/flags) ; 11. I register status (interrupt vector register) ;============================================================================== sub_0770h: ; Complete CPU State Save Entry Point ld sp,011ech ;0770 Set stack pointer to register save area (0x011EC) push hl ;0773 Save main HL register pair push iy ;0774 Save IY index register (2 bytes) push ix ;0776 Save IX index register (2 bytes) exx ;0778 Switch to alternate register set push hl ;0779 Save alternate HL register pair push de ;077a Save alternate DE register pair push bc ;077b Save alternate BC register pair ex af,af' ;077c Switch to alternate AF register push af ;077d Save alternate AF (accumulator/flags) exx ;077e Switch back to main register set ex af,af' ;077f Switch back to main AF register push de ;0780 Save main DE register pair push bc ;0781 Save main BC register pair push af ;0782 Save main AF (accumulator/flags) ld a,i ;0783 Load interrupt vector register into A push af ;0785 Save interrupt vector register status ld a,(011d6h) ;0786 Load debug control parameters from system config rra ;0789 Rotate right bit 0 (extract interrupt enable flag) rra ;078a Rotate right bit 1 (extract trace mode flag) and 001h ;078b Mask to keep only bit 0 (interrupt enable for user) ld (011d6h),a ;078d Store processed debug control back to memory ld a,013h ;0790 Load interrupt vector base 0x13 (table at 0x1300) ld i,a ;0792 Set interrupt vector register for system operation im 2 ;0794 Set interrupt mode 2 (vectored interrupts) ei ;0796 Enable interrupts for system operation ld sp,013feh ;0797 Set stack pointer to system stack area (near top of RAM) ret ;079a Return with complete CPU state saved ; ============================================================================= ; USER PROGRAM EXECUTION ENGINE ; ============================================================================= ; Purpose: Restore all CPU registers and transfer control to user program ; Operation: Complete register restoration from saved state, then execute ; Input: Stack contains saved register state, execution address in HL ;============================================================================== ; USER PROGRAM EXECUTION ENGINE (sub_079bh) - CRITICAL SYSTEM COMPONENT ;============================================================================== ; Purpose: Complete register restoration and user program execution ; Entry: Called from 0x0467 after breakpoint installation or direct execution ; Operation: Restore ALL CPU state → Execute user program → Handle completion ; Exit: User program runs with full CPU state, returns via interrupt/break ; ; EXECUTION FLOW: ; 1. Breakpoint installed at target address (0x0479) ; 2. Control transferred to execution controller (0x0467) ; 3. Register restoration engine called (sub_079bh) ; 4. Complete CPU state restored from memory (0x011D8) ; 5. User program executed via jp (hl) ; 6. Returns via interrupt handler when breakpoint hit or error occurs ; ; REGISTER SAVE AREA LAYOUT (0x011D8): ; • AF (main accumulator/flags) ; • BC (main register pair) ; • DE (main register pair) ; • AF' (alternate accumulator/flags) ; • BC' (alternate register pair) ; • DE' (alternate register pair) ; • HL' (alternate register pair) ; • IX (index register X) ; • IY (index register Y) ; • SP (user stack pointer at 0x011EC) ;============================================================================== sub_079bh: ; User Program Execution Engine - Heart of debugger execution pop hl ;079b Get return address from stack (user program target address) ld sp,011d8h ;079c Point stack pointer to register save area at 0x011D8 pop af ;079f Restore main AF (accumulator + flags) from save area pop bc ;07a0 Restore main BC register pair from save area pop de ;07a1 Restore main DE register pair from save area ex af,af' ;07a2 Switch to alternate AF register (prepare for alt restore) exx ;07a3 Switch to alternate BC,DE,HL registers (prepare for alt restore) pop af ;07a4 Restore alternate AF register from save area pop bc ;07a5 Restore alternate BC register from save area pop de ;07a6 Restore alternate DE register from save area pop hl ;07a7 Restore alternate HL register (contains execution target!) pop ix ;07a8 Restore IX index register from save area pop iy ;07aa Restore IY index register from save area exx ;07ac Switch back to main register set (BC,DE,HL) ex af,af' ;07ad Switch back to main AF register ld sp,(011ech) ;07ae Restore user's original stack pointer from 0x011EC jp (hl) ;07b2 EXECUTE USER PROGRAM! Jump to target in HL register ;============================================================================== ; INTERRUPT/ERROR HANDLER (0x07B3) ;============================================================================== ; Purpose: Handle interrupts or errors, display "BREAK AT " message ; Called from 0x0066 during error conditions or break events ; This appears to be a debugging/error reporting mechanism ;============================================================================== l07b3h: ld (011d4h),hl ;07b3 ; Save HL register for later restoration ld hl,l07c1h ;07b6 ; Load address of continuation routine ex (sp),hl ;07b9 ; Exchange with return address on stack retn ;07ba ; Return from interrupt/error l07bch: ld (011d4h),hl ;07bc ; Save HL register to memory location 011d4h pop hl ;07bf ; Restore HL from stack dec hl ;07c0 ; Decrement HL (adjust return address or pointer) l07c1h: ld (011ech),sp ;07c1 ; Save current stack pointer to 011ech ld sp,01400h ;07c5 ; Set new stack pointer to 0x1400 (top of RAM) call sub_0770h ;07c8 ; Save all CPU registers and setup interrupt mode 2 ld de,(011eah) ;07cb ; Load DE from memory pointer 011eah ld hl,(011f0h) ;07cf ; Load HL from memory pointer 011f0h and a ;07d2 ; Clear carry flag for subtraction sbc hl,de ;07d3 ; Compare HL and DE (subtract DE from HL) jr nz,l07dfh ;07d5 ; If not equal, jump to boot message routine ld hl,011d0h ;07d7 ; Point to counter at 011d0h dec (hl) ;07da ; Decrement the counter jp nz,l0472h ;07db ; If counter not zero, jump to l0472h inc (hl) ;07de ; Restore counter (prevent underflow) ; ============================================================================= ; BREAKPOINT/INTERRUPT HANDLER - Display Break Location= ; ============================================================================ ; Purpose: Display "BREAK AT XXXX" message when execution is interrupted ; Input: DE contains the address where the break/interrupt occurred ; Output: "BREAK AT XXXX" followed by return to monitor prompt ; Used by: Breakpoint system, interrupt handlers, debugging features ; ============================================================================= l07dfh: ; Breakpoint Display Handler ld hl,l0803h ;07df ; Point to "BREAK AT " message string call l00fdh ;07e2 ; Output the "BREAK AT " text to console ex de,hl ;07e5 ; DE = address where break occurred call sub_06b8h ;07e6 ; Display break address in 4-digit hex (XXXX format) call sub_072ah ;07e9 ; Output newline/formatting jp l02cch ;07ec ; Return to monitor command prompt l07efh: push hl ;07ef push af ;07f0 call sub_04ebh ;07f1 ld hl,(011d6h) ;07f4 ld a,h ;07f7 ld i,a ;07f8 bit 0,l ;07fa jr z,l07ffh ;07fc ei ;07fe l07ffh: pop af ;07ff pop hl ;0800 reti ;0801 l0803h: defb 0x42 ;0803 B defb 0x52 ;0804 R defb 0x45 ;0805 E defb 0x41 ;0806 A defb 0x4b ;0807 K defb 0x20 ;0808 defb 0x41 ;0809 A defb 0x54 ;080a T defb 0x20 ;080b defb 0x00 ;080c sub_080dh: ld a,(011f6h) ;080d ld c,a ;0810 call sub_0127h ;0811 ld hl,01169h ;0814 ld (011f4h),hl ;0817 ld b,0ffh ;081a l081ch: push bc ;081c ; Save character count and buffer position call l0134h ;081d ; Get character from input (blocks until available) cp 020h ;0820 ; Compare with space character (0x20) jr c,l083ch ;0822 ; Jump to special character handler if control character (0x00-0x1F) cp 07fh ;0824 ; Compare with DEL character (0x7F) jr z,l083ch ;0826 ; Jump to special character handler for DEL (same as backspace) ld (hl),a ;0828 inc hl ;0829 call sub_0127h ;082a pop bc ;082d djnz l081ch ;082e l0830h: ld (hl),00dh ;0830 call sub_0862h ;0832 ld hl,01169h ;0835 ld a,(hl) ;0838 jp l0677h ;0839 l083ch: pop bc ;083c cp 00dh ;083d ; Check for CR (Carriage Return, Enter key) jr z,l0830h ;083f ; Jump to end input processing if Enter pressed cp 008h ;0841 ; Check for Backspace (0x08) - character deletion jr z,l0849h ;0843 ; Jump to backspace handler cp 07fh ;0845 ; Check for DEL (0x7F) - alternative character deletion jr nz,l081ch ;0847 ; Continue input loop if not a special character ;============================================================================== ; BACKSPACE/DELETE CHARACTER HANDLER (0x0849) ;============================================================================== ; Purpose: Handle character deletion during input (Backspace 0x08 or DEL 0x7F) ; Implements standard line editing by removing the previous character from both ; the input buffer and the terminal display. ; ; Visual Feedback Sequence: ; 1. Send Backspace (0x08) - moves cursor left one position ; 2. Send Space (0x20) - overwrites the character with blank ; 3. Send Backspace (0x08) - moves cursor back to correct position ; ; Buffer Management: ; - Decrements buffer pointer (HL) to remove character ; - Increments remaining character count (B) ; - Prevents deletion beyond start of input buffer ; ; This provides standard terminal line editing behavior expected by users. ;============================================================================== l0849h: ld a,b ;0849 ; Load remaining character count inc a ;084a ; Increment to test for buffer underflow l084bh: jr z,l081ch ;084b ; Jump back to input loop if at buffer start (no chars to delete) push bc ;084d ; Save character count and position ld c,008h ;084e ; Load Backspace character (0x08) call sub_0127h ;0850 ; Send backspace to terminal (move cursor left) ld c,020h ;0853 ; Load Space character (0x20) call sub_0127h ;0855 ; Send space to terminal (erase character) ld c,008h ;0858 ; Load Backspace character (0x08) again call sub_0127h ;085a ; Send backspace to terminal (reposition cursor) pop bc ;085d ; Restore character count and position inc b ;085e ; Increment remaining character count (one less char used) dec hl ;085f ; Move buffer pointer back one position jr l081ch ;0860 ; Return to main input loop ;============================================================================== ; NEWLINE OUTPUT ROUTINE (0x0862) ;============================================================================== ; Purpose: Send carriage return and line feed to console ; This routine outputs a proper newline sequence (CR+LF) to move the cursor ; to the beginning of the next line on the terminal. ; ; Input: None ; Output: CR (0x0D) followed by LF (0x0A) sent to console ; Used by: Console formatting, command completion, line breaks in output ; ; Technical Details: ; • Preserves BC register during operation ; • Uses sub_0127h (console output with transmitter ready check) ; • Implements standard DOS/Windows-style line ending (CR+LF) ; • Essential for proper terminal cursor positioning ;============================================================================== sub_0862h: push bc ;0862 ; Save BC register ld c,00dh ;0863 ; Load Carriage Return character (CR, 0x0D) call sub_0127h ;0865 ; Send CR to console (move cursor to line start) ld c,00ah ;0868 ; Load Line Feed character (LF, 0x0A) call sub_0127h ;086a ; Send LF to console (move cursor to next line) pop bc ;086d ; Restore BC register ret ;086e ; Return ;============================================================================== ; PORT INPUT/OUTPUT COMMAND (I/O Operations) - (0x086F-0x0886) ;============================================================================== ; Purpose: Interactive port I/O operations for hardware testing and control ; Allows user to read from and write to I/O ports with hex parameters ; ; Operation: ; 1. Check for 'U' modifier (possibly "UP" or "UPDATE" command) ; 2. Parse port address from user input ; 3. Read current value from port and display it ; 4. Prompt user for new value (or 'Q' to quit without change) ; 5. If new value provided, write it to the port ; ; Usage: I PPPP [VV] where PPPP=port address, VV=optional value to write ; Interactive: Shows current port value, prompts for new value ;============================================================================== l086fh: ; Port I/O command entry point call sub_065eh ;086f ; Get next character from input buffer cp 055h ;0872 ; Check if character is 'U' (0x55) jp z,l0924h ;0874 ; If 'U', jump to special U command handler call sub_0680h ;0877 ; Parse port address from user input → HL ld c,l ;087a ; Load port address low byte into C ld b,h ;087b ; Load port address high byte into B in a,(c) ;087c ; Read current value from I/O port push bc ;087e ; Save port address call sub_0708h ;087f ; Display current port value in hex + prompt for input pop bc ;0882 ; Restore port address ret z ;0883 ; Return if user pressed 'Q' (quit without changes) out (c),a ;0884 ; Write new value (from user input) to I/O port ret ;0886 ; Return ;============================================================================== ; ARITHMETIC CALCULATOR COMMAND (+ Addition/Subtraction) - (0x0887-0x089C) ;============================================================================== ; Purpose: Perform arithmetic operations on two hex values ; Calculates both addition (A+B) and subtraction (A-B) results ; Displays both results in hex format for comparison ; ; Operation: ; 1. Parse first hex parameter (A) ; 2. Parse second hex parameter (B) ; 3. Calculate A+B (addition result) ; 4. Calculate A-B (subtraction result) ; 5. Display both results in hex format ; ; Usage: + AAAA BBBB (where AAAA and BBBB are hex values) ; Output: Shows both sum and difference in hex format ;============================================================================== l0887h: ; Arithmetic calculator entry point call sub_0680h ;0887 ; Parse first hex parameter → HL (value A) push hl ;088a ; Save first parameter (A) call sub_0680h ;088b ; Parse second hex parameter → HL (value B) ex de,hl ;088e ; Move second parameter (B) to DE pop hl ;088f ; Restore first parameter (A) to HL push hl ;0890 ; Save first parameter again for subtraction add hl,de ;0891 ; Calculate A + B (addition) call sub_06b8h ;0892 ; Display addition result in hex format pop hl ;0895 ; Restore first parameter (A) or a ;0896 ; Clear carry flag for subtraction sbc hl,de ;0897 ; Calculate A - B (subtraction) call sub_06b8h ;0899 ; Display subtraction result in hex format jp sub_072ah ;089c ; Add newline and flush output buffer ; ============================================================================= ; LOAD/TRANSFER DATA COMMAND (L command) - Memory/Storage Operations ; ============================================================================= ; Purpose: Load or transfer data between memory locations or external storage ; Input: User enters "L" optionally followed by hex parameters ; Operation: Performs data loading/transfer operations with address management ; Storage: Working address stored at 0x11CD for ongoing operations ; Features: Supports data checksums, address calculations, and transfer loops ; ============================================================================= l089fh: ; L Command (Load/Transfer) Entry Point call sub_0917h ;089f Initialize/setup routine for load operations call sub_0680h ;08a2 Parse optional hex parameter from user input jr nz,l08aah ;08a5 If parameter provided, use it as load address ld hl,l0000h ;08a7 Default to address 0x0000 if no parameter given l08aah: ; Load operation setup ld (011cdh),hl ;08aa Store load/transfer address at 0x11CD (working address) ld c,011h ;08ad Set up for operations (C=0x11, might be record type/command) call sub_099dh ;08af Call data processing routine (load/transfer handler) l08b2h: ; Data format parsing loop call sub_0997h ;08b2 Get next character from input stream cp 03ah ;08b5 Compare with ':' character (0x3A = ASCII colon) jr nz,l08b2h ;08b7 Keep searching until ':' found (record start marker) call sub_08f8h ;08b9 Parse hex byte (record length/type) ld b,a ;08bc Store parsed value in B register (byte count) call sub_08efh ;08bd Parse hex address (load destination address) or h ;08c0 Check if address is valid (OR with H register) or b ;08c1 Check if byte count is valid (OR with B register) jr nz,l08cch ;08c2 call sub_08efh ;08c4 ld a,013h ;08c7 jp sub_099dh ;08c9 l08cch: call sub_08f8h ;08cc add a,b ;08cf add a,l ;08d0 add a,h ;08d1 ld c,a ;08d2 ld de,(011cdh) ;08d3 add hl,de ;08d7 l08d8h: call sub_08f8h ;08d8 ld (hl),a ;08db inc hl ;08dc add a,c ;08dd ld c,a ;08de djnz l08d8h ;08df call sub_08f8h ;08e1 add a,c ;08e4 jr z,l08b2h ;08e5 ld c,013h ;08e7 call sub_099dh ;08e9 jp l02d9h ;08ec sub_08efh: call sub_08f8h ;08ef ld h,a ;08f2 call sub_08f8h ;08f3 ld l,a ;08f6 ret ;08f7 sub_08f8h: push bc ;08f8 call sub_0907h ;08f9 add a,a ;08fc add a,a ;08fd add a,a ;08fe add a,a ;08ff ld b,a ;0900 call sub_0907h ;0901 add a,b ;0904 pop bc ;0905 ret ;0906 sub_0907h: call sub_0997h ;0907 cp 030h ;090a jr c,sub_0907h ;090c cp 03ah ;090e jr c,l0914h ;0910 sub 007h ;0912 l0914h: and 00fh ;0914 ret ;0916 sub_0917h: call sub_0662h ;0917 cp 040h ;091a jp z,l06ech ;091c dec hl ;091f ld (011f4h),hl ;0920 ret ;0923 l0924h: call sub_0917h ;0924 call sub_0680h ;0927 push hl ;092a call sub_0680h ;092b ld c,012h ;092e call sub_099dh ;0930 pop de ;0933 l0934h: push hl ;0934 ld b,010h ;0935 and a ;0937 sbc hl,de ;0938 jr c,l0970h ;093a ld a,h ;093c and a ;093d jr nz,l0946h ;093e ld a,l ;0940 cp b ;0941 jr nc,l0946h ;0942 ld b,a ;0944 inc b ;0945 l0946h: ex de,hl ;0946 ld c,03ah ;0947 call sub_099dh ;0949 ld a,b ;094c call sub_0985h ;094d add a,h ;0950 add a,l ;0951 ld c,a ;0952 call sub_098ah ;0953 sub a ;0956 call sub_0985h ;0957 l095ah: ld a,(hl) ;095a call sub_0985h ;095b add a,c ;095e ld c,a ;095f inc hl ;0960 djnz l095ah ;0961 ld a,c ;0963 neg ;0964 call sub_0985h ;0966 pop de ;0969 ex de,hl ;096a call sub_074dh ;096b jr l0934h ;096e l0970h: pop hl ;0970 ld c,03ah ;0971 call sub_099dh ;0973 ld b,00ah ;0976 ld c,030h ;0978 l097ah: call sub_099dh ;097a djnz l097ah ;097d ld c,014h ;097f call sub_099dh ;0981 ret ;0984 sub_0985h: call sub_06c6h ;0985 jr l098dh ;0988 sub_098ah: call sub_06b8h ;098a l098dh: push hl ;098d ld hl,(011f2h) ;098e dec hl ;0991 ld (011f2h),hl ;0992 pop hl ;0995 ret ;0996 sub_0997h: push bc ;0997 call l0116h ;0998 pop bc ;099b ret ;099c sub_099dh: push bc ;099d call sub_0111h ;099e pop bc ;09a1 ; Restore BC register ret ;09a2 ; Return from routine ;============================================================================== ; CONTROL CHARACTER HANDLER (0x09A3) ;============================================================================== ; Purpose: Process special control characters during input operations ; This routine intercepts and handles special ASCII control characters that ; require immediate system response, providing user control over operations. ; ; Control Characters Handled: ; • 0x03 (ETX, Ctrl+C): Emergency system reset/break ; • 0x13 (XOFF, Ctrl+S): Pause/resume output flow control ; ; Character Processing: ; 1. Call input routine (sub_013ah) to get character ; 2. Check for zero (no character available) ; 3. Compare with control character codes ; 4. Take appropriate action or return ; ; Flow Control Features: ; • Preserves BC register across all operations ; • Returns immediately if no character or unrecognized character ; • Provides clean stack management for nested calls ; • Implements standard terminal control behavior ;============================================================================== sub_09a3h: push bc ;09a3 ; Save BC register call sub_013ah ;09a4 ; Get character from input (keyboard/serial) pop bc ;09a7 ; Restore BC register ret z ;09a8 ; Return if no character available (zero flag set) cp 003h ;09a9 ; Check for ETX (End of Text, Ctrl+C) jr z,l09b6h ;09ab ; Jump to system reset if Ctrl+C pressed cp 013h ;09ad ; Check for XOFF (Ctrl+S, pause) ret nz ;09af ; Return if not XOFF push bc ;09b0 ; Save BC register call l0134h ;09b1 ; Handle XOFF (pause/resume) functionality pop bc ;09b4 ; Restore BC register ret ;09b5 ; Return from XOFF handling ;============================================================================== ; SYSTEM RESET/RESTART ROUTINE (0x09B6) ;============================================================================== ; Purpose: Emergency system reset triggered by Ctrl+C (ETX) character ; This routine provides a clean way to abort current operations and return ; to the monitor command prompt, similar to a "break" or "interrupt" function. ; ; Trigger Conditions: ; • Ctrl+C (0x03 ETX character) received during input processing ; • User wants to abort current operation and return to monitor ; • Emergency recovery from hung or problematic operations ; ; Reset Actions: ; 1. Reset stack pointer to system default (0x1400) ; 2. Jump directly to main monitor command loop ; 3. Bypass any pending operations or nested calls ; ; Technical Details: ; • Stack Reset: SP = 0x1400 (top of RAM workspace) ; • Direct Jump: Goes to 0x02CC (main monitor loop entry) ; • Clean State: Abandons current call stack and variables ; • User Interface: Provides immediate return to ">" prompt ; ; This implements a standard "Ctrl+C break" behavior found in many systems ; of this era, allowing users to escape from problematic situations. ;============================================================================== l09b6h: ld sp,01400h ;09b6 ; Reset stack pointer to system default jp l02cch ;09b9 ; Jump to main monitor command loop (clean restart) ;============================================================================== ; FLOPPY DISK CONTROLLER COMMAND HANDLER (O COMMAND) (0x09BC-0x0A5E) ;============================================================================== ; Purpose: Comprehensive floppy disk operation command with multi-sector support ; The O command is the primary interface for all floppy disk operations including ; read, write, format, and seek operations with automatic multi-sector handling. ; ; COMMAND SYNTAX: ; O D F T S - Disk parameter configuration only ; OS - Special CP/M boot operation (jumps to 0x0FBB) ; ; PARAMETER SPECIFICATION: ; • D (Drive): 0-3 (selects physical floppy drive A: through D:) ; • F (Flags): 0-1 (drive control/head selection: 0=standard, 1=alternate) ; • T (Track): 0-76 (track/cylinder number, max 77 tracks for 8" drives) ; • S (Sectors): 1-26 (sector count per operation, max 27 sectors/track) ; ; IMPORTANT: O command only configures disk parameters. Memory addressing ; is controlled by subsequent R (read) or W (write) commands. ; ; OPERATION MODES: ; 1. SETUP MODE (default): Configures disk parameters for later R/W operations ; 2. SEEK MODE: If S=0, performs head positioning without data transfer ; 3. BOOT MODE: "OS" variant initiates CP/M system boot sequence ; ; ADVANCED FEATURES: ; • Automatic multi-sector transfers across track boundaries ; • Sector increment with track wraparound (sector 27 → track+1, sector 1) ; • Head selection toggle for double-sided drives (controlled by drive status) ; • Memory buffer overflow protection (stops at end address) ; • Error recovery with "DISK ERR" message display ; ; MEMORY PARAMETER STORAGE: ; • 0x1202: Drive number (0-3) - Selects active drive unit ; • 0x1226: Drive control flags (0-1) - Head/side selection ; • 0x1225: Track/cylinder number (0-76) - Current track position ; • 0x1227: Sector count (1-26) - Number of sectors to transfer ; • 0x1200-0x1201: DMA buffer address (16-bit) - Target memory location ; • 0x11F7: Operation ready flag (0xFF when parameters validated) ; • 0x11F8: Function pointer - Points to operation handler routine ; ; EXECUTION FLOW: ; 1. Parameter validation and range checking (drive 0-3, track 0-76, etc.) ; 2. Memory address parsing and buffer setup (start/end address validation) ; 3. Multi-sector loop with automatic sector/track increment ; 4. DMA buffer management and overflow protection ; 5. Error handling with user-friendly "DISK ERR" messages ; ; HARDWARE INTERFACE: ; • NEC µPD765A FDC via ports 0xF0-0xF6 for command/data/status ; • Z80 DMA controller via port 0xF3 for high-speed transfers ; • Drive selection via hardware control lines ; • Track positioning via stepper motor control ; ; ERROR CONDITIONS: ; • Invalid drive number (>3): "ERR" message, return to monitor ; • Invalid track number (>76): "ERR" message, return to monitor ; • Invalid sector count (0 or >26): "ERR" message, return to monitor ; • Disk hardware failure: "DISK ERR" message, return to monitor ; • Memory buffer overflow: Operation stops at end address ; ; SPECIAL OPERATIONS: ; • "OS" command: Bypasses normal parameter parsing, jumps directly to CP/M boot ; • Zero sector count: Performs seek operation without data transfer ; • Single sector: Standard read/write operation ; • Multi-sector: Automatic sector increment with track boundary handling ; ; EXAMPLES: ; O 0 0 5 1 - Configure drive A:, track 5, 1 sector (then use R/W for memory) ; O 1 0 0 10 - Configure drive B:, track 0, 10 sectors (then use R/W for memory) ; O 0 1 10 0 - Seek drive A: to track 10 (no data transfer) ; OS - Boot CP/M operating system from disk ; ; TYPICAL USAGE SEQUENCE: ; O 0 0 5 1 - Configure: Drive A:, track 5, 1 sector ; R 1000 100 - Execute: Read data into memory 1000h-10FFh ;============================================================================== l09bch: ; Floppy Disk Parameter Parser Entry Point call sub_065eh ;09bc Get next character from input buffer cp 053h ;09bf Compare with 'S' (0x53 = ASCII 'S' for special command) jp z,l0fbbh ;09c1 If 'S', jump to special disk handler call sub_0680h ;09c4 Parse hex parameter (drive number) cp 004h ;09c7 Check if drive number >= 4 (invalid) jp nc,l02d9h ;09c9 Jump to error if invalid drive number ld (01202h),a ;09cc Store valid drive number (0-3) call sub_0680h ;09cf Get next parameter from input cp 002h ;09d2 Check if parameter < 2 (valid range) jp nc,l02d9h ;09d4 Jump to error if parameter >= 2 ld (01226h),a ;09d7 Store drive control flags (0 or 1) call sub_0680h ;09da Get next parameter from input cp 04dh ;09dd Check if parameter < 77 (0x4D, max tracks) jp nc,l02d9h ;09df Jump to error if parameter >= 77 ld (01225h),a ;09e2 Store drive parameter/selector (track/cylinder) call sub_0680h ;09e5 Parse final parameter (sector count) or a ;09e8 Check if sector count is zero (invalid) jp z,l02d9h ;09e9 Jump to error if zero sectors specified cp 01bh ;09ec Check if sector count >= 27 (0x1B, max sectors) jp nc,l02d9h ;09ee Jump to error if too many sectors ld (01227h),a ;09f1 Store valid sector count (1-26) ld a,0ffh ;09f4 Load 0xFF (operation ready flag) ld (011f7h),a ;09f6 Set operation status flag (ready for disk operations) ret ;09f9 Return to caller with parameters validated and stored ;============================================================================== ; DISK WRITE COMMAND HANDLER (W COMMAND) (0x09FA-0x09FE) ; ; Purpose: Simplified disk write operation using disk parameters from O command ; This command writes data from memory to floppy disk using disk parameters ; previously configured by the O command, while controlling memory addressing. ; ; Syntax: W AAAA BBBB ; Where: AAAA = Start address of data to write to disk ; BBBB = Length of data to write (number of bytes) ; ; Prerequisite: O command must be used first to configure disk parameters ; (drive number, track, sector count, etc.) ; ; Operation: ; 1. Checks that disk parameters are configured (O command was run) ; 2. Parses memory address and length from W command parameters ; 3. Uses sub_0bf2h which configures FDC for write operations (command 0x04) ; 4. Combines O command disk params with W command memory params for actual I/O ; ; Related Commands: ; - O command (0x09BC): Configures disk parameters (drive, track, sectors) ; - R command (0x09FF): Disk read using O parameters + R memory parameters ;============================================================================== ld hl,l0db1h ;09fa W COMMAND: Load pointer to write parameter block jr l0a0ah ;09fd Jump to common disk operation handler ;============================================================================== ; DISK READ COMMAND HANDLER (R COMMAND) (0x09FF-0x0A09) ; ; Purpose: Simplified disk read operation using disk parameters from O command ; This command reads data from floppy disk to memory using disk parameters ; previously configured by the O command, while controlling memory addressing. ; ; Syntax: R AAAA BBBB ; Where: AAAA = Start address to store data read from disk ; BBBB = Length of data to read (number of bytes) ; ; Prerequisite: O command must be used first to configure disk parameters ; (drive number, track, sector count, etc.) ; ; Operation: ; 1. Checks for 'O' character (alternate entry point to O command) ; 2. Verifies that disk parameters are configured (O command was run) ; 3. Parses memory address and length from R command parameters ; 4. Uses sub_0d2eh which calls sub_0bf2h then validates read status ; 5. Combines O command disk params with R command memory params for actual I/O ;============================================================================== ld hl,l0db1h ;09fa jr l0a0ah ;09fd call sub_065eh ;09ff R COMMAND: Check if parameters are provided cp 04fh ;0a02 Compare with 'O' character (alternate O command entry) jp z,l089fh ;0a04 Jump to O command handler if 'O' character found ld hl,l0dabh ;0a07 Load pointer to read parameter block l0a0ah: ;============================================================================== ; COMMON DISK OPERATION HANDLER (0x0A0A+) ; ; Purpose: Shared entry point for both R and W commands ; Handles parameter validation and initiates disk I/O operations ; ; Input: HL = Pointer to parameter block (0x0DAB for read, 0x0DB1 for write) ; Uses: FDC command bytes (0x03 = READ DATA, 0x04 = WRITE DATA) ; ; This routine validates the operation status, parses memory addresses, ; and coordinates with the NEC µPD765A floppy disk controller. ;============================================================================== ld (011f8h),hl ;0a0a Store parameter block pointer ld hl,011f7h ;0a0d xor a ;0a10 cp (hl) ;0a11 jp z,l02d9h ;0a12 ld (hl),a ;0a15 call l0de0h ;0a16 call sub_0680h ;0a19 push hl ;0a1c call sub_0680h ;0a1d pop de ;0a20 ex de,hl ;0a21 l0a22h: or a ;0a22 inc hl ;0a23 sbc hl,de ;0a24 add hl,de ;0a26 dec hl ;0a27 ret nc ;0a28 ld (01200h),hl ;0a29 push de ;0a2c push hl ;0a2d ld hl,(011f8h) ;0a2e call sub_0da8h ;0a31 jr nc,l0a60h ;0a34 ld hl,01227h ;0a36 ld a,(hl) ;0a39 inc a ;0a3a ld (hl),a ;0a3b cp 01bh ;0a3c jr c,l0a51h ;0a3e ld (hl),001h ;0a40 ld a,(01203h) ;0a42 or a ;0a45 jr z,l0a4dh ;0a46 dec hl ;0a48 ld a,(hl) ;0a49 xor 001h ;0a4a ld (hl),a ;0a4c l0a4dh: jr nz,l0a51h ;0a4d dec hl ;0a4f inc (hl) ;0a50 l0a51h: ld a,(01203h) ;0a51 or a ;0a54 ld hl,l0080h ;0a55 jr z,l0a5bh ;0a58 add hl,hl ;0a5a l0a5bh: pop de ;0a5b add hl,de ;0a5c pop de ;0a5d jr l0a22h ;0a5e l0a60h: ld hl,l0a69h ;0a60 call l00fdh ;0a63 jp l02d9h ;0a66 l0a69h: defb 0x44 ;0a69 D defb 0x49 ;0a6a I defb 0x53 ;0a6b S defb 0x4b ;0a6c K defb 0x20 ;0a6d defb 0x45 ;0a6e E defb 0x52 ;0a6f R defb 0x52 ;0a70 R defb 0x0d ;0a71 RETURN defb 0x0a ;0a72 RETURN defb 0x00 ;0a73 l0a74h: call sub_0680h ;0a74 Get drive number parameter from user input cp 004h ;0a77 Check if drive number >= 4 (invalid) jp nc,l02d9h ;0a79 Jump to error if invalid drive number ld (01202h),a ;0a7c Store current drive number (0-3) call sub_0e43h ;0a7f Execute drive operation jp nc,l0a60h ;0a82 ret ;0a85 l0a86h: call sub_0acbh ;0a86 jp nc,l0a60h ;0a89 ret ;0a8c ;============================================================================== ; FLOPPY DISK CONTROLLER INITIALIZATION (0x0A8D) ;============================================================================== ; Purpose: Initialize NEC µPD765A floppy disk controller and Z80 DMA ; Hardware Setup: ; - Port 0xF6: FDC command/status register ; - Port 0xF3: Z80 DMA control register (standalone Z80 DMA chip) ; - Port 0xF0: FDC main status register ; - Port 0xF4: FDC data register ; ; Z80 DMA Operations: ; - Value 0x08: Enable Z80 DMA for floppy transfers ; - Clear bit 3: Modify DMA transfer mode parameters ; - Two-stage DMA setup for optimal transfer configuration ; ; Operation: ; 1. Send "specify" command to FDC (configure timing parameters) ; 2. Enable Z80 DMA controller for high-speed transfers ; 3. Modify DMA transfer mode settings ; 4. Wait for FDC ready status ; 5. Configure for read/write operations ; ; Returns: Carry flag set if successful, clear if failed ;============================================================================== sub_0a8dh: ld a,003h ;0a8d ; Load FDC "specify" command out (0f6h),a ;0a8f ; Send command to FDC command register ld a,008h ;0a91 ; Load Z80 DMA enable control value out (0f3h),a ;0a93 ; Enable Z80 DMA for floppy operations res 3,a ;0a95 ; Clear bit 3 (modify DMA transfer mode) out (0f3h),a ;0a97 ; Update Z80 DMA control register ld bc,sub_011ch ;0a99 ; Load timeout/delay parameters call sub_0f0ah ;0a9c ; Call delay/timing routine ld bc,l0000h ;0a9f ; Initialize counter for FDC status polling ;============================================================================== ; FDC STATUS POLLING LOOP (0x0AA2) ;============================================================================== ; Purpose: Wait for FDC to become ready for command execution ; This is a critical timing loop that ensures the NEC µPD765A FDC is ready ; to accept commands before proceeding with disk operations. ; ; Hardware Details: ; - Port 0xF0: NEC µPD765A Main Status Register (MSR) ; - Bit 7 of MSR: RQM (Request for Master) - indicates FDC ready state ; - Timeout: 65536 iterations (BC=0x0000 decrements to 0xFFFF then 0x0000) ; ; Status Register Interpretation: ; - MSR bit 7 = 1: FDC ready to accept commands/data ; - MSR bit 7 = 0: FDC busy, continue polling ; - Expected final state: MSR = 0x80 (only RQM bit set) ; ; Returns: ; - Zero flag set: Timeout occurred (FDC never became ready) ; - Zero flag clear: FDC ready, A contains final status ; - A = 0x00: Success (MSR was exactly 0x80) ; - A ≠ 0x00: Warning (MSR had unexpected bits set) ;============================================================================== l0aa2h: dec bc ;0aa2 ; Decrement timeout counter ld a,b ;0aa3 ; Load high byte of counter or c ;0aa4 ; OR with low byte to test for zero ret z ;0aa5 ; Return if timeout (BC reached 0x0000) in a,(0f0h) ;0aa6 ; Read FDC Main Status Register bit 7,a ;0aa8 ; Test RQM bit (Request for Master) jr z,l0aa2h ;0aaa ; Loop if FDC not ready (RQM=0) xor 080h ;0aac ; XOR with 0x80 to check if only RQM bit set ret nz ;0aae ; Return if other status bits are set (error condition) ;============================================================================== ; FDC COMMAND EXECUTION SETUP (0x0AAF) ;============================================================================== ; Purpose: Execute FDC commands and wait for completion status ; This section handles the command execution phase after the FDC is ready. ; It coordinates with the NEC µPD765A to execute disk operations. ; ; Operation Flow: ; 1. Call command execution routine (sub_0ba7h) ; 2. Wait for command completion (status 0x80) ; 3. Setup interrupt vector for DMA completion ; 4. Configure DMA parameters for data transfer ; ; Hardware Configuration: ; - Port 0xF4: FDC data register for parameter passing ; - Port 0xF6: FDC command register ; - Memory 0x1334: Interrupt vector table pointer ; - Address 0x0BB6: DMA completion handler ; ; Status Codes: ; - 0x80: Command execution successful, ready for data transfer ; - Other: Command still executing or error condition ;============================================================================== l0aafh: call sub_0ba7h ;0aaf ; Execute FDC command sequence ret nc ;0ab2 ; Return if command execution failed cp 080h ;0ab3 ; Check if execution status is 0x80 (success) jr nz,l0aafh ;0ab5 ; Loop until command completes successfully ld hl,l0bb6h ;0ab7 ; Load address of DMA completion handler ld (01334h),hl ;0aba ; Store in interrupt vector table ld a,030h ;0abd ; Load DMA control parameter out (0f4h),a ;0abf ; Send to FDC data register ld a,0d7h ;0ac1 ; Load FDC command parameter out (0f6h),a ;0ac3 ; Send command to FDC ld a,001h ;0ac5 ; Load final parameter out (0f6h),a ;0ac7 ; Complete command sequence scf ;0ac9 ; Set carry flag (success indicator) ret ;0aca ; Return with success status ;============================================================================== ; FLOPPY DISK CONTROLLER MASTER ROUTINE (0x0ACB) ;============================================================================== ; Purpose: Main floppy disk operation coordinator ; Calls sub-routines to: ; 1. Initialize FDC and prepare for disk operations (sub_0a8dh) ; 2. Execute disk read/write operations (sub_0ae9h) ; 3. Loop through multiple drives/sectors (0x0AD8 loop) ; ; This appears to be the high-level disk I/O interface that coordinates ; multiple disk operations across different drives (up to 4 drives/sectors) ;============================================================================== sub_0acbh: call sub_0a8dh ;0acb ; Initialize FDC hardware and prepare for operation ret nc ;0ace ; Return if FDC initialization failed call sub_0ae9h ;0acf ; Execute the actual disk operation ret nc ;0ad2 xor a ;0ad3 A = 0 (start with drive 0) ld iy,01205h ;0ad4 Point IY to drive status table l0ad8h: ; Multi-drive boot loop (tries drives 0,1,2,3) push af ;0ad8 Save current drive number ld (01202h),a ;0ad9 Set current drive number (0x1202) call sub_0b1ch ;0adc Attempt to read boot sector from current drive pop af ;0adf Restore drive number inc iy ;0ae0 Move to next drive status entry inc a ;0ae2 Next drive number (0→1→2→3) cp 004h ;0ae3 Check if tried all 4 drives jr nz,l0ad8h ;0ae5 Loop until all drives tested scf ;0ae7 Set carry flag (success) ret ;0ae8 Return from multi-drive scan ;============================================================================== ; FDC COMMAND PARAMETER SETUP (0x0AE9) ;============================================================================== ; Purpose: Prepare NEC µPD765A command parameters for disk operations ; This routine builds the command parameter block required by the FDC to ; execute read/write operations. The parameters are assembled from various ; system variables and formatted according to NEC µPD765A specifications. ; ; Memory Layout - FDC Parameter Block (0x1213-0x1215): ; • 0x1213: Command byte (0x03 = READ DATA command) ; • 0x1214: Drive/Head selection and DMA control ; • 0x1215: Track/Sector/Size parameters ; ; Parameter Sources: ; • 0x120B: Drive geometry configuration (tracks, density) ; • 0x120A: Head selection and DMA mode settings ; • 0x1209: Sector size and format parameters ; • 0x1204: Additional drive control flags ; ; NEC µPD765A Command Format: ; - Bit manipulation ensures proper head selection and DMA modes ; - Rotation and masking operations format multi-bit parameters ; - Command block follows standard FDC command structure ;============================================================================== sub_0ae9h: ld hl,01213h ;0ae9 ; Point to FDC command parameter block push hl ;0aec ; Save base pointer for later use ld (hl),003h ;0aed ; Set command byte: 0x03 = READ DATA command inc hl ;0aef ; Move to drive/head parameter byte (0x1214) ld a,(0120bh) ;0af0 ; Load drive geometry configuration and 00fh ;0af3 ; Mask to get lower 4 bits (drive geometry) sub 011h ;0af5 ; Subtract 0x11 (adjust for FDC format) cpl ;0af7 ; Complement bits (invert for FDC encoding) rlca ;0af8 ; Rotate left 4 positions to place in upper nibble rlca ;0af9 ; (4 rotations = shift left 4 bits) rlca ;0afa rlca ;0afb ld (hl),a ;0afc ; Store formatted drive parameter ld a,(0120ah) ;0afd ; Load head selection and DMA mode rrca ;0b00 ; Rotate right 4 positions to get lower nibble rrca ;0b01 ; (4 rotations = shift right 4 bits) rrca ;0b02 rrca ;0b03 and 00fh ;0b04 ; Mask to keep only lower 4 bits or (hl) ;0b06 ; Combine with previous drive parameter ld (hl),a ;0b07 ; Store combined drive/head parameter inc hl ;0b08 ; Move to track/sector parameter byte (0x1215) ld a,(01209h) ;0b09 ; Load sector size and format configuration res 0,a ;0b0c ; Clear bit 0 (modify sector size encoding) ld (hl),a ;0b0e ; Store modified sector parameter ld a,(01204h) ;0b0f ; Load additional drive control flags and 001h ;0b12 ; Mask to get only bit 0 (specific control flag) or (hl) ;0b14 ; Combine with sector parameter ld (hl),a ;0b15 ; Store final track/sector/control parameter ld b,003h ;0b16 ; Set parameter count: 3 bytes for FDC command pop hl ;0b18 ; Restore base pointer to command block jp l0b64h ;0b19 ; Jump to FDC command execution routine ;============================================================================== ; FDC OPERATION WITH PARAMETER MANAGEMENT (0x0B1C) ;============================================================================== ; Purpose: Execute FDC operations with automatic parameter backup/restore ; This routine provides a higher-level interface for disk operations that ; temporarily modifies drive parameters and ensures they are properly restored ; even if the operation fails. ; ; Operation Flow: ; 1. Prepare FDC for operation (sub_0b33h) ; 2. Backup current drive parameter (0x1225) ; 3. Set temporary parameter (0x03) for operation ; 4. Execute disk operation (sub_0c05h) ; 5. Restore original parameter regardless of operation result ; 6. Verify FDC is ready for next operation ; ; Memory Locations: ; • 0x1225: Drive parameter/selector register (backed up and restored) ; • Value 0x03: Temporary parameter setting for this operation type ; ; Error Handling: ; - Parameters are restored even if disk operation fails ; - Final FDC readiness check before returning ; - Carry flag indicates overall operation success ;============================================================================== sub_0b1ch: call sub_0b33h ;0b1c ; Prepare FDC for operation ld a,(01225h) ;0b1f ; Load current drive parameter push af ;0b22 ; Save parameter on stack for restoration ld a,003h ;0b23 ; Load temporary parameter value ld (01225h),a ;0b25 ; Set temporary drive parameter call sub_0c05h ;0b28 ; Execute disk operation pop af ;0b2b ; Restore original parameter from stack ld (01225h),a ;0b2c ; Write back original drive parameter call sub_0b33h ;0b2f ; Verify FDC readiness after operation ret c ;0b32 ; Return if FDC is ready (carry set = success) ;============================================================================== ; FDC RECALIBRATE AND COMMAND SETUP (0x0B33) ;============================================================================== ; Purpose: Prepare FDC for operation with recalibrate command and status monitoring ; This routine initializes the FDC to a known state and sets up a recalibrate ; command for reliable disk operations. Used both before and after disk operations ; to ensure the drive heads are properly positioned. ; ; Operation Sequence: ; 1. Set drive status to 0xFF (reset/initialize state) ; 2. Execute low-level FDC preparation (sub_0d2eh) ; 3. Clear status flags and setup command parameters ; 4. Configure RECALIBRATE command (0x07) with drive parameters ; 5. Wait for command completion with timeout monitoring ; ; Hardware Details: ; • IY register: Points to drive status table (set by caller) ; • 0x1226: Drive control flags cleared during operation ; • 0x1213: Command byte set to 0x07 (RECALIBRATE command) ; • 0x124A: Operation completion status flag ; ; NEC µPD765A RECALIBRATE Command: ; - Moves drive head to track 0 (cylinder 0) ; - Establishes known reference position for subsequent seeks ; - Required after drive selection or power-on sequences ;============================================================================== sub_0b33h: ld (iy+000h),0ffh ;0b33 ; Set drive status to 0xFF (initialize state) call sub_0d2eh ;0b37 ; Execute low-level FDC preparation routine ret nc ;0b3a ; Return if FDC preparation failed (carry clear) xor a ;0b3b ; Load 0 into accumulator ld (01226h),a ;0b3c ; Clear drive control flags ld hl,01213h ;0b3f ; Point to FDC command parameter block push hl ;0b42 ; Save command block pointer ld (hl),007h ;0b43 ; Set command byte: 0x07 = RECALIBRATE command inc hl ;0b45 ; Move to next parameter byte call sub_0b7bh ;0b46 ; Setup additional command parameters xor a ;0b49 ; Load 0 into accumulator ld (0124ah),a ;0b4a ; Clear operation completion status flag ld b,002h ;0b4d ; Set parameter count: 2 bytes for RECALIBRATE command pop hl ;0b4f ; Restore command block pointer call l0b64h ;0b50 ; Send command to FDC ret nc ;0b53 ; Return if command transmission failed ;============================================================================== ; RECALIBRATE COMPLETION MONITORING (0x0B54) ;============================================================================== ; Purpose: Wait for RECALIBRATE command completion with status validation ; Monitors the operation completion flag and validates the final status to ; ensure the recalibrate operation completed successfully. ; ; Status Monitoring: ; • 0x124A: Operation completion flag (0=pending, non-zero=completed) ; • Expected completion status: 0x20 (recalibrate successful) ; • Status mask 0xF8: Checks upper 5 bits for error conditions ; ; Returns: ; • Carry set: RECALIBRATE completed successfully, drive ready ; • Carry clear: RECALIBRATE failed or timeout occurred ;============================================================================== l0b54h: ld a,(0124ah) ;0b54 ; Read operation completion status or a ;0b57 ; Test if operation completed (non-zero) jr z,l0b54h ;0b58 ; Loop until completion flag is set and 0f8h ;0b5a ; Mask upper 5 bits to check for errors xor 020h ;0b5c ; Compare with expected success status (0x20) ret nz ;0b5e ; Return with carry clear if not successful ld (iy+000h),a ;0b5f ; Store final status (0x00) in drive status scf ;0b62 ; Set carry flag (operation successful) ret ;0b63 ; Return with success status ;============================================================================== ; FLOPPY CONTROLLER I/O TRANSMITTER (0x0B64) ;============================================================================== ; Purpose: Send command bytes to floppy controller via I/O ports ; Input: HL = pointer to command buffer, B = byte count, C = 0xF1 (data port) ; ; Function: ; - Waits for floppy controller ready (port 0xF0 status bits 0-4 clear) ; - Polls bit 7 of status port 0xF0 for command ready signal ; - Checks bit 6 for transfer direction/error condition ; - Uses OUTI instruction to send bytes from buffer to port 0xF1 ; - Continues until all B bytes transmitted ; ; Ports Used: ; - 0xF0: Floppy controller status register ; - Bit 7: Command ready flag ; - Bit 6: Direction/error flag ; - Bits 0-4: Various status conditions ; - 0xF1: Floppy controller data register (via register C) ; ; Returns: Carry set on success, clear on error ;============================================================================== l0b64h: ld c,0f1h ;0b64 Set port C = 0xF1 (FDC data register) l0b66h: in a,(0f0h) ;0b66 Read FDC status register (port 0xF0) and 01fh ;0b68 Mask lower 5 bits (status/error flags) jr nz,l0b66h ;0b6a Loop until all status flags are clear l0b6ch: in a,(0f0h) ;0b6c Read FDC status register again bit 7,a ;0b6e Test bit 7 (command ready flag) jr z,l0b6ch ;0b70 Loop until FDC is ready for command and 040h ;0b72 Test bit 6 (direction/error flag) ret nz ;0b74 Return with error if direction flag set outi ;0b75 Output byte from (HL) to port C, increment HL, decrement B jr nz,l0b6ch ;0b77 Loop until all B bytes transmitted (B≠0) scf ;0b79 Set carry flag = success (all bytes transmitted) ret ;0b7a Return to caller with success status ;============================================================================== ; FLOPPY COMMAND PARAMETER BUILDER (0x0B7B) ;============================================================================== ; Purpose: Build drive and head selection parameters for floppy commands ; Input: HL = pointer to command buffer (pointing to parameter byte location) ; ; Function: ; - Reads drive selection from 0x1226, rotates left twice (bits 6-7 → bits 0-1) ; - Combines with head selection from 0x1202 ; - Stores combined drive/head parameter in command buffer ; - Advances buffer pointer for next parameter ; ; Parameter Format: ; - Bits 0-1: Drive number (from 0x1226 bits 6-7) ; - Other bits: Head selection and flags (from 0x1202) ; ; Memory Locations: ; - 0x1226: Drive selection (bits 6-7 used) ; - 0x1202: Head selection and other flags ;============================================================================== sub_0b7bh: ld a,(01226h) ;0b7b rlca ;0b7e rlca ;0b7f ld (hl),a ;0b80 ld a,(01202h) ;0b81 or (hl) ;0b84 ld (hl),a ;0b85 inc hl ;0b86 ret ;0b87 ;============================================================================== ; FLOPPY CONTROLLER RESPONSE READER (0x0B88) ;============================================================================== ; Purpose: Read response bytes from floppy controller after command execution ; ; Function: ; - Sets up response buffer at 0x121C ; - Uses port 0xF1 for data input (via register C) ; - Implements timeout loop (B=0x0A iterations) ; - Polls port 0xF0 status register: ; - Bit 4: Data ready flag ; - Bit 7: Controller ready flag ; - Bit 6: Direction/completion flag ; - Uses INI instruction to read bytes from port 0xF1 to buffer ; - Returns first response byte and sets carry on success ; ; Timeout Handling: ; - 10-iteration outer loop for timeout protection ; - Inner delay loop for timing control ; - Returns with carry clear on timeout ; ; Returns: A = first response byte, Carry = success flag ;============================================================================== l0b88h: ld hl,0121ch ;0b88 ld c,0f1h ;0b8b l0b8dh: ld b,00ah ;0b8d l0b8fh: djnz l0b8fh ;0b8f l0b91h: in a,(0f0h) ;0b91 bit 4,a ;0b93 jr z,l0ba2h ;0b95 bit 7,a ;0b97 jr z,l0b91h ;0b99 and 040h ;0b9b ret z ;0b9d ini ;0b9e jr l0b8dh ;0ba0 l0ba2h: ld a,(0121ch) ;0ba2 scf ;0ba5 ret ;0ba6 sub_0ba7h: ld hl,01213h ;0ba7 ld (hl),008h ;0baa ld bc,001f1h ;0bac call l0b6ch ;0baf ret nc ;0bb2 jp l0b88h ;0bb3 l0bb6h: push af ;0bb6 push hl ;0bb7 push bc ;0bb8 push de ;0bb9 l0bbah: in a,(0f0h) ;0bba ; Read floppy controller main status register bit 7,a ;0bbc ; Test READY bit (controller ready) jr z,l0bbah ;0bbe ; Wait until controller is ready bit 6,a ;0bc0 ; Test DATA_REQUEST bit (controller needs data) jr z,l0bd9h ;0bc2 ; If no data request, handle differently ld a,083h ;0bc4 ; Load DMA command 0x83 out (0fch),a ;0bc6 ; Send command to Z80 DMA controller port 0xFC ; ; 0x83 = DMA control command for FDC coordination ld (0124bh),a ;0bc8 call l0b88h ;0bcb ld hl,0121ch ;0bce ld de,0120ch ;0bd1 ld bc,00007h ;0bd4 ldir ;0bd7 l0bd9h: call sub_0ba7h ;0bd9 jr nc,l0bebh ;0bdc cp 080h ;0bde jr z,l0bebh ;0be0 bit 5,a ;0be2 jr z,l0bd9h ;0be4 ld (0124ah),a ;0be6 jr l0bd9h ;0be9 l0bebh: pop de ;0beb pop bc ;0bec pop hl ;0bed pop af ;0bee ei ;0bef reti ;0bf0 ;============================================================================== ; FLOPPY DISK CONTROLLER WRITE COMMAND SETUP (sub_0bf2h) - 0x0BF2-0x0C04 ;============================================================================== ; Purpose: Configure NEC µPD765A FDC for WRITE DATA operations (command 0x04) ; Called by: W command (0x09FA), sub_0d2eh (R command), and other disk routines ; ; CRITICAL FUNCTION: This routine sets up the FDC command 0x04 (WRITE DATA) ; and prepares the controller for disk write operations using parameters ; previously configured by the O command. ; ; INPUT CONTEXT: ; - O command has configured: drive (0x1202), track (0x1225), sectors (0x1227) ; - Calling command (W/R) provides: memory address, data length ; - FDC command buffer at 0x1213-0x1215 ready for command setup ; ; OPERATION SEQUENCE: ; 1. Set up command buffer with WRITE DATA command (0x04) ; 2. Add drive/head parameters via sub_0b7bh ; 3. Transmit command to FDC via ports 0xF0/0xF1 ; 4. Return status for caller processing ; ; FDC COMMAND 0x04: WRITE DATA - Writes sector data to floppy disk ; Buffer Layout: [0x1213]=0x04, [0x1214]=drive/head, [0x1215]=track ; ; HARDWARE INTERFACE: ; - Port 0xF0: FDC main status register (ready/busy status) ; - Port 0xF1: FDC data register (command and parameter transfer) ; - Memory 0x1213-0x1215: Command parameter block ; ; RETURNS: Status in accumulator, carry flag indicates success/failure ;============================================================================== sub_0bf2h: ld hl,01213h ;0bf2 Point to FDC command buffer (command parameter block) push hl ;0bf5 Save buffer pointer for later restoration ld (hl),004h ;0bf6 Set FDC command = 0x04 (WRITE DATA command) inc hl ;0bf8 Move to next buffer position (0x1214) call sub_0b7bh ;0bf9 Add drive/head parameters from O command config pop hl ;0bfc Restore command buffer pointer to start (0x1213) ld b,002h ;0bfd Set parameter count = 2 bytes (command + drive/head) call l0b64h ;0bff Transmit command buffer to FDC via port 0xF1 jp l0b88h ;0c02 Jump to FDC response handler and return status ; End sub_0bf2h: Command 0x04 configured and sent, response processing in l0b88h ;============================================================================== ;============================================================================== ; DISK SEEK AND STATUS CHECK ROUTINE (sub_0c05h) - 0x0C05-0x0C2E ;============================================================================== ; Purpose: Execute SEEK command (0x0F) to position disk head on specified track ; Called by: Various disk operations that need head positioning before I/O ; ; OPERATION SEQUENCE: ; 1. Verify write capability by calling sub_0d2eh (WRITE command validation) ; 2. If write OK, execute SEEK command (0x0F) to position head on track ; 3. Wait for seek completion and verify positioning status ; ; CRITICAL FUNCTION: This ensures the disk head is properly positioned before ; read/write operations, using the track number configured by O command. ; ; INPUT REQUIREMENTS: ; - Track number at 0x1225 (configured by O command) ; - Drive/head parameters at 0x1226, 0x1202 (from O command) ; - FDC must be ready for command execution ; ; FDC COMMAND 0x0F: SEEK - Positions disk head to specified track/cylinder ; Buffer Layout: [0x1213]=0x0F, [0x1214]=drive/head, [0x1215]=track ; ; RETURNS: Carry set on success, clear on failure ;============================================================================== sub_0c05h: call sub_0d2eh ;0c05 Test write capability (validates FDC write readiness) ret nc ;0c08 Return if write validation failed (no seek possible) ld hl,01213h ;0c09 Point to FDC command buffer for SEEK command setup push hl ;0c0c Save command buffer pointer for later restoration ld (hl),00fh ;0c0d Set FDC command = 0x0F (SEEK command) inc hl ;0c0f Move to parameter position (0x1214) call sub_0b7bh ;0c10 Add drive/head parameters from O command configuration ld a,(01225h) ;0c13 Load target track number (configured by O command) ld (hl),a ;0c16 Store track number in command buffer (0x1215) xor a ;0c17 Clear accumulator (A = 0) ld (0124ah),a ;0c18 Clear seek completion status flag pop hl ;0c1b Restore command buffer pointer to start (0x1213) ld b,003h ;0c1c Set parameter count = 3 bytes (cmd + drive/head + track) call l0b64h ;0c1e Transmit SEEK command to FDC via port 0xF1 ret nc ;0c21 Return if command transmission failed l0c22h: ; SEEK COMPLETION WAIT LOOP - Monitor FDC status for seek operation completion ld a,(0124ah) ;0c22 Check seek completion status flag or a ;0c25 Test if status has been updated (non-zero = complete) jr z,l0c22h ;0c26 Loop until seek operation completes and 0f8h ;0c28 Mask status bits: check for error conditions (bits 3-7) xor 020h ;0c2a XOR with 0x20: test for expected completion status ret nz ;0c2c Return with error if status doesn't match expected scf ;0c2d Set carry flag = success (seek completed successfully) ret ;0c2e Return to caller with success status ; End sub_0c05h: SEEK command completed, head positioned on target track ;============================================================================== ; DISK I/O OPERATION DISPATCH ROUTINE (l0c2fh/l0c33h) - 0x0C2F-0x0C69 ;============================================================================== ; Purpose: High-level disk I/O operation coordinator with dual entry points ; Entry Points: ; l0c2fh: Entry for write operations (sets operation type = 6) ; l0c33h: Entry for read operations (sets operation type = 5) ; Called by: Disk I/O functions requiring complete read/write operation sequence ; ; Operation Sequence: ; 1. Set operation type (read=5, write=6) in memory location 0x1223 ; 2. Check drive configuration status and exit if not configured ; 3. Configure drive parameters, FDC commands, and DMA setup ; 4. Execute FDC operation with up to 9 retry attempts ; 5. Perform final status validation and error checking ; 6. Return with success/failure status ; ; Returns: Carry flag set = success, clear = failure ; Memory: Uses 0x1223 for operation type, 0x124B for error status ;============================================================================== l0c2fh: ld a,006h ;0c2f Set operation type = 6 (WRITE operation) jr l0c35h ;0c31 Jump to common I/O processing l0c33h: ld a,005h ;0c33 Set operation type = 5 (READ operation) l0c35h: ld hl,01223h ;0c35 Point to operation type storage location ld (hl),a ;0c38 Store operation type (5 or 6) in memory ld a,(01204h) ;0c39 Load drive configuration byte from memory or a ;0c3c Test if drive is configured (non-zero = configured) ret nz ;0c3d Return immediately if drive not configured call sub_0c6ah ;0c3e Call drive configuration setup routine call sub_0b7bh ;0c41 Call FDC command preparation routine call sub_0c73h ;0c44 Call DMA parameter configuration routine call sub_0d2eh ;0c47 Call FDC status validation routine ret nc ;0c4a Return with error if FDC validation failed call sub_0ca0h ;0c4b Call FDC operation setup routine call sub_0cc5h ;0c4e Call DMA transfer configuration routine xor a ;0c51 Clear accumulator (A = 0) ld (0124bh),a ;0c52 Clear error status flag in memory ld hl,01223h ;0c55 Point to operation type location ld b,009h ;0c58 Set retry count = 9 attempts call l0b64h ;0c5a Call FDC command execution routine ret nc ;0c5d Return with error if command execution failed call sub_0d11h ;0c5e Call final status check routine ret nc ;0c61 Return with error if final status check failed ld a,(0120ch) ;0c62 Load final operation status byte and 0c0h ;0c65 Mask upper 2 bits (critical error flags) ret nz ;0c67 Return with error if critical errors detected scf ;0c68 Set carry flag = success (operation completed) ret ;0c69 Return to caller with success status sub_0c6ah: ld a,(01203h) ;0c6a rrca ;0c6d rrca ;0c6e or (hl) ;0c6f ld (hl),a ;0c70 inc hl ;0c71 ret ;0c72 sub_0c73h: ld hl,l0c90h ;0c73 ld de,01228h ;0c76 jr l0c81h ;0c79 sub_0c7bh: ld hl,l0c98h ;0c7b ld de,01215h ;0c7e l0c81h: ld a,(01203h) ;0c81 add a,a ;0c84 add a,a ;0c85 ld c,a ;0c86 ld b,000h ;0c87 add hl,bc ;0c89 ld bc,00004h ;0c8a Set copy length = 4 bytes (copy 4 bytes of lookup data) ldir ;0c8d Copy data block: HL→DE for BC bytes (data table copy) ret ;0c8f Return after data table has been copied to target location ;============================================================================== ; DISK PARAMETER LOOKUP TABLE 1 (l0c90h) - 0x0C90-0x0C97 ;============================================================================== ; Purpose: Disk operation parameter lookup table for drive configuration ; Usage: Referenced by sub_0c73h, copied to memory location 0x1228+ ; Format: 8-byte data table containing disk controller configuration values ;============================================================================== l0c90h: defb 000h ;0c90 Parameter byte 0: Base configuration value defb 01ah ;0c91 Parameter byte 1: Drive timing/control setting defb 020h ;0c92 Parameter byte 2: Drive mode flags defb 080h ;0c93 Parameter byte 3: Drive status/control flags defb 01ah, 00eh ;0c94 Parameter bytes 4-5: Extended configuration (0x0E1A) defb 0ffh ;0c96 Parameter byte 6: End marker/control flag defb 000h ;0c97 Parameter byte 7: Padding/reserved ;============================================================================== ; DISK PARAMETER LOOKUP TABLE 2 (l0c98h) - 0x0C98-0x0C9F ;============================================================================== ; Purpose: Alternate disk operation parameter table for different operations ; Usage: Referenced by sub_0c7bh, copied to memory location 0x1215+ ; Format: 8-byte data table for alternate disk controller configuration ;============================================================================== l0c98h: defb 000h ;0c98 Parameter byte 0: Alternate base configuration defb 01ah ;0c99 Parameter byte 1: Alternate timing setting defb 0edh ;0c9a Parameter byte 2: Alternate mode flags defb 0e5h ;0c9b Parameter byte 3: Alternate control settings defb 01ah, 036h ;0c9c Parameter bytes 4-5: Extended alternate config (0x361A) defb 0e5h ;0c9e Parameter byte 6: Alternate end marker defb 000h ;0c9f Parameter byte 7: Alternate padding/reserved ;============================================================================== ; Z80 DMA CONTROLLER CONFIGURATION ROUTINE (sub_0ca0h) - 0x0CA0-0x0CBC ;============================================================================== ; Purpose: Configure Z80 DMA controller for disk data transfer operations ; Called by: Disk I/O routines that need DMA setup for high-speed transfers ; ; OPERATION: Sets up DMA channel parameters for floppy disk data transfers ; This routine configures the Z80 DMA controller to handle high-speed data ; movement between the floppy disk controller and system memory. ; ; DMA CONFIGURATION SEQUENCE: ; 1. Calculate DMA parameters based on drive status and transfer requirements ; 2. Send WR1 register setup (0x47) with drive-specific parameters ; 3. Send WR3 register setup (0x57) with transfer control parameters ; ; HARDWARE INTERFACE: ; - Port 0xF4: Z80 DMA WR1 register (memory address and count setup) ; - Port 0xF5: Z80 DMA WR3 register (transfer mode and control) ; - Memory 0x1203: Drive status flags (used for DMA parameter calculation) ; ; PARAMETERS: ; - D register: Drive-specific DMA configuration value ; - E register: Transfer mode and control settings ;============================================================================== sub_0ca0h: ld a,(01203h) ;0ca0 Load drive status flags from system configuration inc a ;0ca3 Increment for DMA calculation (A = drive_status + 1) ld d,a ;0ca4 Store calculated drive parameter in D register ld e,080h ;0ca5 Set transfer control mode = 0x80 (DMA mode flags) jr l0cadh ;0ca7 Jump to common DMA configuration routine ;============================================================================== ; ALTERNATE DMA CONFIGURATION ENTRY POINT (sub_0ca9h) - 0x0CA9-0x0CAC ;============================================================================== ; Purpose: Alternative DMA setup with fixed parameters for specific operations ; Used for: Standard disk operations with preset DMA configuration ;============================================================================== sub_0ca9h: ld d,001h ;0ca9 Set fixed drive parameter = 0x01 (standard mode) ld e,068h ;0cab Set fixed transfer control = 0x68 (alternate mode) ;============================================================================== ; COMMON DMA REGISTER CONFIGURATION (l0cadh) - 0x0CAD-0x0CBC ;============================================================================== ; Purpose: Send DMA configuration commands to Z80 DMA controller ; Input: D = drive/address parameter, E = transfer control parameter ; ; Z80 DMA PROGRAMMING SEQUENCE: ; Command 0x47: WR1 register - Memory address and byte count configuration ; Command 0x57: WR3 register - Transfer mode, timing, and control settings ; ; The Z80 DMA controller requires specific command sequences to configure ; memory-to-peripheral transfers for high-speed floppy disk operations. ;============================================================================== l0cadh: ld c,0f4h ;0cad Set port address = 0xF4 (Z80 DMA WR1 register) ld a,047h ;0caf Load DMA command = 0x47 (WR1: address/count setup) out (c),a ;0cb1 Send WR1 command to DMA controller out (c),d ;0cb3 Send drive/address parameter to DMA WR1 register inc c ;0cb5 Move to next DMA port = 0xF5 (WR3 register) ld a,057h ;0cb6 Load DMA command = 0x57 (WR3: transfer mode setup) out (c),a ;0cb8 Send WR3 command to DMA controller out (c),e ;0cba Send transfer control parameter to DMA WR3 register ret ;0cbc Return to caller with DMA controller configured ; End DMA configuration: Z80 DMA ready for high-speed disk data transfers ;============================================================================== ; DMA TRANSFER LENGTH SETUP ROUTINE (sub_0cbdh) - 0x0CBD-0x0CFA ;============================================================================== ; Purpose: Configure DMA transfer parameters and initiate disk data transfer ; Called by: Format and disk I/O operations requiring DMA data movement ; ; Operation: ; 1. Calculate transfer length based on operation type and FDC command ; 2. Set up DMA configuration block from ROM template ; 3. Configure memory addresses and transfer parameters ; 4. Send complete DMA configuration to Z80 DMA controller ; ; Transfer Types: Different lengths for read/write vs format operations ; Memory: Uses 0x122C as DMA configuration workspace, ports 0xFC for DMA ;============================================================================== sub_0cbdh: ld hl,00068h ;0cbd Set default transfer length to 0x68 (104 bytes) ld a,(01213h) ;0cc0 Load FDC command byte from command buffer jr l0cd2h ;0cc3 Jump to common DMA setup processing sub_0cc5h: ld hl,l0080h ;0cc5 Set base transfer length to 0x80 (128 bytes) ld a,(01203h) ;0cc8 Load drive status/configuration byte or a ;0ccb Test if drive supports extended operations jr z,l0ccfh ;0ccc Skip length doubling if standard operation add hl,hl ;0cce Double transfer length (0x80 → 0x100 = 256 bytes) l0ccfh: ld a,(01223h) ;0ccf Load disk operation parameter for processing l0cd2h: dec hl ;0cd2 Decrement transfer length (adjust for DMA requirements) push hl ;0cd3 Save adjusted transfer length on stack ld hl,l0cfbh ;0cd4 Point to DMA configuration template in ROM ld de,0122ch ;0cd7 Point to DMA configuration workspace in RAM ld bc,00016h ;0cda Set copy length to 22 bytes (0x16) ldir ;0cdd Copy DMA template from ROM to RAM workspace pop hl ;0cdf Restore transfer length from stack ld (01235h),hl ;0ce0 Store transfer length in DMA block (bytes 8-9) ld hl,(01200h) ;0ce3 Load DMA buffer address from memory ld (01233h),hl ;0ce6 Store buffer address in DMA block (bytes 6-7) and 001h ;0ce9 Test bit 0 of operation parameter (direction flag) rlca ;0ceb Rotate left (bit 0 → bit 1) rlca ;0cec Rotate left (bit 1 → bit 2, final position) ld hl,0123eh ;0ced Point to DMA control byte in configuration block or (hl) ;0cf0 OR with existing control settings ld (hl),a ;0cf1 Store updated control byte with direction flag ld hl,0122ch ;0cf2 Point to start of DMA configuration block ld bc,016fch ;0cf5 Set B=22 (bytes to send), C=0xFC (DMA port) otir ;0cf8 Send 22-byte DMA configuration to Z80 DMA controller ret ;0cfa Return with DMA controller configured and ready ;============================================================================== ; DMA CONFIGURATION DATA BLOCK (l0cfbh) - 0x0CFB-0x0D10 (22 bytes) ;============================================================================== ; Purpose: 22-byte DMA configuration data block copied to RAM at 0x122C ; Usage: Referenced by routine at 0cd7h, copied via BC=0016h + LDIR ;============================================================================== l0cfbh: defb 0c3h ;0cfb DMA WR0: Base register - Enable DMA, memory-to-I/O transfer defb 0c3h ;0cfc DMA WR1: Port A address low byte (or timing control) defb 0c3h ;0cfd DMA WR1: Port A address high byte defb 0c3h ;0cfe DMA WR2: Block length low byte (or port config) defb 0c3h ;0cff DMA WR2: Block length high byte defb 0c3h ;0d00 DMA WR3: Port A timing and control settings defb 079h ;0d01 DMA WR4: Port B configuration (0x79 = I/O port mode) defb 000h ;0d02 DMA WR5: Port B address low byte (0x00) defb 000h ;0d03 DMA WR5: Port B address high byte (0x00) defb 000h ;0d04 DMA WR6: Port B timing control (0x00 = default) defb 000h ;0d05 Reserved/padding byte for alignment defb 014h ;0d06 DMA command: Load (0x14 = Load WR4 command) defb 028h ;0d07 DMA timing: Cycle length configuration defb 089h ;0d08 DMA control: Transfer mode and direction flags defb 0f2h ;0d09 DMA status: Ready/enable flags (0xF2) defb 082h ;0d0a DMA port config: FDC data register selection defb 083h ;0d0b DMA command: Enable/start transfer (0x83) defb 0cfh ;0d0c DMA interrupt: Vector and control (0xCF) defb 001h ;0d0d DMA counter: Transfer count low byte defb 083h ;0d0e DMA control: Final command byte (0x83) defb 0cfh ;0d0f DMA vector: Interrupt vector high byte defb 007h ;0d10 DMA mask: End-of-block mask/control (final config byte) ;============================================================================== ; DISK OPERATION STATUS POLLING ROUTINE (sub_0d11h) - 0x0D11-0x0D2D ;============================================================================== ; Purpose: Wait for disk operation completion by polling status register ; Called by: Disk I/O routines that need to wait for operation completion ; ; Operation: ; 1. Initialize BC=0x0000 (timeout counter: B=0, C=0 = 65536 iterations max) ; 2. Poll status location 0x124B repeatedly until non-zero (operation done) ; 3. If status becomes non-zero, set carry flag and return (success) ; 4. If timeout expires, send DMA command 0x83 and call FDC init ; 5. Clear carry flag and return (timeout/error) ; ; Memory: 0x124B = FDC operation status (0=busy, non-zero=complete) ; Ports: 0xFC = Z80 DMA controller command port ;============================================================================== sub_0d11h: ld bc,l0000h ;0d11 Initialize timeout counter (BC=0x0000 = 65536 max loops) l0d14h: ; Status polling loop entry point ld a,(0124bh) ;0d14 Load FDC operation status from memory or a ;0d17 Test if status is non-zero (operation complete) scf ;0d18 Set carry flag (success indicator) ret nz ;0d19 Return with carry set if operation completed ld a,(0124bh) ;0d1a Load status again (double-check for reliability) or a ;0d1d Test status again scf ;0d1e Set carry flag again ret nz ;0d1f Return with carry if now complete djnz l0d14h ;0d20 Decrement B counter, loop if not zero dec c ;0d22 Decrement C counter (outer loop) jr nz,l0d14h ;0d23 Continue polling if C not zero (timeout not reached) ld a,083h ;0d25 Load DMA command 0x83 (timeout cleanup) out (0fch),a ;0d27 Send command to Z80 DMA controller port 0xFC ; 0x83 = DMA control command for disk operations call sub_0a8dh ;0d29 Call FDC initialization routine (recovery attempt) or a ;0d2c Clear carry flag (indicate timeout/error) ret ;0d2d Return with carry clear (failure) ;============================================================================== ; FDC WRITE STATUS CHECK ROUTINE (sub_0d2eh) - 0x0D2E-0x0D36 ;============================================================================== ; Purpose: Check if FDC is ready for write operations by testing status bit 5 ; Called by: Write command routines and disk operation validators ; ; Operation: ; 1. Call sub_0bf2h (FDC write command setup) to get current FDC status ; 2. Return with carry clear if FDC setup failed (not ready) ; 3. Test bit 5 of status register (write ready indicator) ; 4. Return with carry clear if bit 5 is zero (write not ready) ; 5. Return with carry set if bit 5 is set (write ready) ; ; Returns: Carry flag = FDC write ready status (1=ready, 0=not ready) ;============================================================================== sub_0d2eh: call sub_0bf2h ;0d2e Call FDC write command setup, get status in A ret nc ;0d31 Return with carry clear if FDC setup failed and 020h ;0d32 Test bit 5 of status (write ready indicator) ret z ;0d34 Return with carry clear if bit 5 = 0 (not ready) scf ;0d35 Set carry flag (write ready confirmed) ret ;0d36 ;============================================================================== ; DISK SEEK AND RETRY OPERATION (sub_0d37h) - 0x0D37-0x0D59 ;============================================================================== ; Purpose: Perform disk seek operation with retry logic and status tracking ; Called by: Disk operation routines that need head positioning and validation ; ; Operation: ; 1. Check if FDC is ready for write operations (via sub_0d2eh) ; 2. If not ready, return with carry clear (failure) ; 3. Set retry counter to 2 attempts (B=0x02) ; 4. For each attempt: ; - Call sub_0c05h (disk seek and status check) ; - Store current track number from 0x1225 to IY+0 (drive status table) ; - If seek successful (carry set), return immediately ; - Call sub_0b1ch (disk read operation) ; - If read fails, return with carry clear ; - Increment error counter at 0x1244 ; - Retry if attempts remaining ; 5. Clear carry and return if all retries exhausted ; ; Memory: 0x1225=track number, 0x1244=error counter, IY=drive status pointer ;============================================================================== sub_0d37h: call sub_0d2eh ;0d37 Check if FDC is ready for write operations ret nc ;0d3a Return with carry clear if FDC not ready ld b,002h ;0d3b Set retry counter to 2 attempts l0d3dh: ; Retry loop entry point push bc ;0d3d Save retry counter on stack call sub_0c05h ;0d3e Call disk seek and status check routine pop bc ;0d41 Restore retry counter from stack ld a,(01225h) ;0d42 Load current track number from memory ld (iy+000h),a ;0d45 Store track number in drive status table (IY+0) ret c ;0d48 Return with carry set if seek was successful push bc ;0d49 Save retry counter again call sub_0b1ch ;0d4a Call disk read operation to verify positioning pop bc ;0d4d Restore retry counter ret nc ;0d4e Return with carry clear if read operation failed ld hl,(01244h) ;0d4f Load error counter from memory location 0x1244 inc hl ;0d52 Increment error counter (track retry attempt) ld (01244h),hl ;0d53 Store updated error counter back to memory djnz l0d3dh ;0d56 Decrement retry counter, loop if more attempts remain or a ;0d58 Clear carry flag (all retries exhausted, operation failed) ret ;0d59 Return with carry clear indicating failure ;============================================================================== ; FDC STATUS VALIDATION ROUTINE (l0d5ah) - 0x0D5A-0x0D66 ;============================================================================== ; Purpose: Validate FDC status bits for specific disk operation conditions ; Called by: Disk operation routines that need to check controller readiness ; ; Operation: ; 1. Call sub_0bf2h to get current FDC status byte ; 2. XOR with 0x20 (flip bit 5 - write ready indicator) ; 3. AND with 0x60 (test bits 5&6 - data direction and write ready) ; 4. Return with non-zero flag if status invalid (operation not ready) ; 5. If status valid, load parameter table pointer and continue ; ; Status Bits: Bit 5=write ready, Bit 6=data direction ; Memory: 0x120D=FDC status register (NOTE: Missing from main memory map) ; Returns: Zero flag set=valid status, Zero flag clear=invalid status ;============================================================================== l0d5ah: call sub_0bf2h ;0d5a Call FDC write setup, get status byte in A xor 020h ;0d5d XOR with 0x20 (flip bit 5 - write ready bit) and 060h ;0d5f AND with 0x60 (test bits 5&6 - data direction & write ready) ret nz ;0d61 Return with non-zero if status invalid (not ready) ld hl,l0c33h ;0d62 Load pointer to disk parameter table (valid status) jr l0d6eh ;0d65 Jump to common parameter processing routine ;============================================================================== ; ALTERNATE FDC VALIDATION ENTRY POINT (l0d67h) - 0x0D67-0x0D6D ;============================================================================== ; Purpose: Alternative entry point for FDC validation with different table ; Operation: Checks write readiness then uses alternate parameter table ;============================================================================== l0d67h: call sub_0d2eh ;0d67 Check if FDC is ready for write operations ret nc ;0d6a Return with carry clear if FDC not ready ld hl,l0c2fh ;0d6b Load pointer to alternate disk parameter table ;============================================================================== ; COMMON PARAMETER PROCESSING (l0d6eh) - 0x0D6E+ ;============================================================================== ; Purpose: Common routine for processing disk parameters with retry logic ; Input: HL = pointer to parameter table (l0c33h or l0c2fh) ;============================================================================== l0d6eh: ld b,005h ;0d6e Set retry counter to 5 attempts l0d70h: ; Main retry loop entry point push bc ;0d70 Save retry counter on stack push hl ;0d71 Save parameter table pointer on stack call sub_0da8h ;0d72 Call parameter table function via HL register pop hl ;0d75 Restore parameter table pointer from stack pop bc ;0d76 Restore retry counter from stack ret c ;0d77 Return with carry set if operation successful push hl ;0d78 Save parameter table pointer again ld a,(0120dh) ;0d79 Load FDC status register (error condition flags) and 085h ;0d7c Test bits 0,2,7 (specific error conditions) jr z,l0d87h ;0d7e Skip error counter increment if no error ld hl,(01246h) ;0d80 Load error counter A from memory inc hl ;0d83 Increment error counter A ld (01246h),hl ;0d84 Store updated error counter A back to memory l0d87h: ; Check additional error conditions ld a,(0120dh) ;0d87 Load FDC status register again and 020h ;0d8a Test bit 5 (write ready/direction error) jr z,l0d95h ;0d8c Skip error counter B if bit 5 clear ld hl,(01248h) ;0d8e Load error counter B from memory inc hl ;0d91 Increment error counter B ld (01248h),hl ;0d92 Store updated error counter B back to memory l0d95h: ; Check extended error conditions ld a,(0120eh) ;0d95 Load FDC extended status register and 012h ;0d98 Test bits 1,4 (additional error flags) jr z,l0da3h ;0d9a Skip general error counter if no error ld hl,(01244h) ;0d9c Load general error counter from memory inc hl ;0d9f Increment general error counter ld (01244h),hl ;0da0 Store updated general error counter back to memory l0da3h: ; End of retry loop pop hl ;0da3 Restore parameter table pointer from stack djnz l0d70h ;0da4 Decrement retry counter, loop if more attempts remain or a ;0da6 Clear carry flag (all retries exhausted, operation failed) ret ;0da7 Return with carry clear indicating failure ;============================================================================== ; INDIRECT FUNCTION CALL ROUTINES (0x0DA8-0x0DA9) ;============================================================================== ; Purpose: Dynamic function dispatching via register indirect calls ; Used by: Parameter processing routines for flexible operation selection ;============================================================================== sub_0da8h: jp (hl) ;0da8 Jump to address stored in HL register (parameter table function) sub_0da9h: jp (ix) ;0da9 Jump to address stored in IX register (operation function) ;============================================================================== ; DISK READ OPERATION ENTRY POINTS (l0dabh/l0db1h) - 0x0DAB-0x0DDF ;============================================================================== ; Purpose: High-level disk read operations with different validation approaches ; Two entry points using different FDC validation routines: ; - l0dabh: Uses l0d67h validation (write readiness check) ; - l0db1h: Uses l0d5ah validation (status bit manipulation) ;============================================================================== l0dabh: ; Read operation entry point A ld ix,l0d67h ;0dab Set IX to point to FDC validation routine (write check) jr l0db5h ;0daf Jump to common read operation setup l0db1h: ; Read operation entry point B ld ix,l0d5ah ;0db1 Set IX to point to FDC validation routine (status bits) l0db5h: ; Common read operation setup ld iy,01205h ;0db5 Point IY to drive status table base address ld b,002h ;0db9 Set operation retry counter to 2 attempts ld a,(01202h) ;0dbb Load current drive number from memory ld e,a ;0dbe Copy drive number to E register ld d,000h ;0dbf Clear D register (DE = drive number, 0-3) add iy,de ;0dc1 Add drive offset to status table pointer (IY += drive) ld a,(01225h) ;0dc3 Load current track number from memory cp (iy+000h) ;0dc6 Compare with track in drive status table jr z,l0dd1h ;0dc9 Skip seek if already on correct track l0dcbh: ; Seek and read retry loop push bc ;0dcb Save retry counter on stack call sub_0d37h ;0dcc Call disk seek and retry operation pop bc ;0dcf Restore retry counter from stack ret nc ;0dd0 Return with carry clear if seek failed l0dd1h: ; Execute read operation push bc ;0dd1 Save retry counter on stack call sub_0da9h ;0dd2 Call FDC validation function via IX register pop bc ;0dd5 Restore retry counter from stack ret c ;0dd6 Return with carry set if validation successful push bc ;0dd7 Save retry counter again call sub_0b1ch ;0dd8 Call actual disk read operation pop bc ;0ddb Restore retry counter djnz l0dcbh ;0ddc Decrement retry counter, loop if more attempts remain or a ;0dde Clear carry flag (all retries exhausted, read failed) ret ;0ddf Return with carry clear indicating failure ;============================================================================== ; FLOPPY DISK STATUS CHECK ROUTINE (0x0DE0) ;============================================================================== ; Purpose: Check floppy disk controller status and extract specific status bit ; Entry Point: l0de0h - Called from interrupt vector 0x000B and multiple locations ; ; Function: ; - Sends status command (0x04) to floppy controller via ports 0xF0/0xF1 ; - Reads back status response from floppy controller ; - Extracts bit 3 from status (rotated to bit 0) ; - Stores extracted bit at memory location 0x1203 ; ; Status bit extracted (original bit 3) likely indicates: ; - Drive ready condition, Track 0 detection, Write protect, or Index pulse ; ; Used as: Interrupt service routine and general floppy status check ; Ports: 0xF0 (status), 0xF1 (data), 0xFC (control) ;============================================================================== l0de0h: call sub_0bf2h ;0de0 Call FDC write setup, get status byte in A register rrca ;0de3 Rotate right (bit 3 → bit 2) rrca ;0de4 Rotate right (bit 2 → bit 1) rrca ;0de5 Rotate right (bit 1 → bit 0, original bit 3 now in bit 0) and 001h ;0de6 Mask to keep only bit 0 (original FDC status bit 3) ld (01203h),a ;0de8 Store extracted status bit at drive status location ret ;0deb Return with extracted status bit in A ;============================================================================== ; DISK FORMAT OPERATION ROUTINE (sub_0dech) - 0x0DEC-0x0E1E ;============================================================================== ; Purpose: Execute complete disk format operation with FDC command setup ; Called by: Format command routines that need to prepare and format tracks ; ; Operation Sequence: ; 1. Check FDC write readiness via sub_0d2eh ; 2. Set up FDC command 0x0D (FORMAT TRACK) in command buffer ; 3. Configure disk parameters and DMA setup ; 4. Execute format operation and wait for completion ; 5. Validate completion status and return result ; ; FDC Command: 0x0D = FORMAT TRACK (formats entire track with sector headers) ; Memory: 0x1213=command buffer, 0x124B=operation status, 0x120C=completion status ;============================================================================== sub_0dech: call sub_0d2eh ;0dec Check if FDC is ready for write operations ret nc ;0def Return with carry clear if FDC not ready for format ld hl,01213h ;0df0 Point HL to FDC command buffer ld (hl),00dh ;0df3 Set command byte to 0x0D (FORMAT TRACK command) call sub_0c6ah ;0df5 Call disk parameter configuration routine call sub_0b7bh ;0df8 Call drive/head selection setup routine call sub_0e1fh ;0dfb Call track/sector parameter table setup call sub_0ca9h ;0dfe Call DMA controller configuration routine call sub_0cbdh ;0e01 Call DMA transfer initialization routine xor a ;0e04 Clear A register (A = 0) ld (0124bh),a ;0e05 Clear operation status flag (0 = operation in progress) ld hl,01213h ;0e08 Point HL to FDC command buffer start ld b,006h ;0e0b Set command length to 6 bytes (FORMAT TRACK parameters) call l0b64h ;0e0d Transmit 6-byte format command to FDC via port 0xF1 ret nc ;0e10 Return with carry clear if command transmission failed l0e11h: ; Wait for format operation completion ld a,(0124bh) ;0e11 Load operation status flag from memory or a ;0e14 Test if operation completed (non-zero = done) jr z,l0e11h ;0e15 Loop until format operation completes ld a,(0120ch) ;0e17 Load FDC completion status register l0e1ah: ; Validate format completion status and 0c0h ;0e1a Test bits 6&7 (completion and error status flags) ret nz ;0e1c Return with non-zero if format errors detected scf ;0e1d Set carry flag (format operation successful) ret ;0e1e Return with carry set indicating successful format ;============================================================================== ; FORMAT SECTOR DATA GENERATION ROUTINE (sub_0e1fh) - 0x0E1F-0x0E42 ;============================================================================== ; Purpose: Generate sector data pattern for format track operation ; Called by: Format operation routine (sub_0dech) to create sector headers ; ; Operation: ; 1. Call sub_0c7bh to set up track/sector parameter tables ; 2. Load drive configuration from memory (drive status, head flags, track) ; 3. Set up DMA buffer at 0x1000 for format data generation ; 4. Generate 26 sector entries (0x1A = 26 sectors) with format pattern: ; - Track number (from 0x1225) ; - Head/drive flags (from 0x1226) ; - Sector number (incrementing: 1,2,3...26) ; - Sector size (from 0x1203) ; ; Memory Layout: Creates format data at 0x1000+ for FDC FORMAT TRACK command ; Format: Each sector = 4 bytes (track, head, sector, size) × 26 sectors = 104 bytes ;============================================================================== sub_0e1fh: call sub_0c7bh ;0e1f Call track/sector parameter table setup routine ld a,(01203h) ;0e22 Load drive status/sector size from memory ld e,a ;0e25 Store sector size parameter in E register ld a,(01226h) ;0e26 Load drive control flags (head selection) ld c,a ;0e29 Store head/drive flags in C register ld a,(01225h) ;0e2a Load current track number from memory ld d,001h ;0e2d Set initial sector number to 1 (first sector) ld b,01ah ;0e2f Set loop counter to 0x1A (26 sectors per track) ld hl,01000h ;0e31 Point HL to format data buffer at 0x1000 ld (01200h),hl ;0e34 Store buffer address in DMA address register l0e37h: ; Sector format data generation loop ld (hl),a ;0e37 Store track number (A) in format buffer inc hl ;0e38 Move to next byte in buffer ld (hl),c ;0e39 Store head/drive flags (C) in format buffer inc hl ;0e3a Move to next byte in buffer ld (hl),d ;0e3b Store sector number (D) in format buffer inc hl ;0e3c Move to next byte in buffer ld (hl),e ;0e3d Store sector size (E) in format buffer inc hl ;0e3e Move to next 4-byte sector entry inc d ;0e3f Increment sector number (1→2→3...→26) djnz l0e37h ;0e40 Decrement sector counter, loop until all 26 sectors done ret ;0e42 Return with format data buffer prepared at 0x1000 ;============================================================================== ; COMPLETE DISK FORMAT OPERATION (sub_0e43h) - 0x0E43-0x0E86 ;============================================================================== ; Purpose: Format entire disk with comprehensive drive setup and validation ; Called by: System initialization routines for complete disk preparation ; ; Operation Sequence: ; 1. Validate FDC status and drive readiness ; 2. Initialize drive status table and perform read test ; 3. Format all tracks (0-76, total 77 tracks) with both head configurations ; 4. Handle single/double-sided drive detection and formatting ; ; Track Coverage: Formats tracks 0 through 76 (0x4D-1 = 77 tracks total) ; Head Support: Handles both head 0 and head 1 for double-sided drives ;============================================================================== sub_0e43h: call sub_0bf2h ;0e43 Call FDC write setup, get status byte xor 020h ;0e46 XOR with 0x20 (flip write ready bit) and 060h ;0e48 Test bits 5&6 (data direction and write ready) ret nz ;0e4a Return if FDC not ready for format operations call l0de0h ;0e4b Call FDC status check, extract drive status bit ld iy,01205h ;0e4e Point IY to drive status table base ld a,(01202h) ;0e52 Load current drive number (0-3) ld e,a ;0e55 Copy drive number to E register ld d,000h ;0e56 Clear D register (DE = drive offset) add iy,de ;0e58 Point IY to current drive's status entry call sub_0b1ch ;0e5a Perform initial drive read test ret nc ;0e5d Return if drive read test failed xor a ;0e5e Clear A register (start with track 0) ld (01225h),a ;0e5f Set starting track number to 0 l0e62h: ; Main track formatting loop (tracks 0-76) call sub_0c05h ;0e62 Call disk seek and status check for current track ret nc ;0e65 Return if seek to track failed xor a ;0e66 Clear head selection (start with head 0) ld (01226h),a ;0e67 Set head selection to 0 (first head) call sub_0dech ;0e6a Call format track operation for head 0 ret nc ;0e6d Return if head 0 format failed ld a,(01203h) ;0e6e Load drive capabilities/head count from status or a ;0e71 Test if drive supports multiple heads jr z,l0e7bh ;0e72 Skip head 1 format if single-sided drive ld (01226h),a ;0e74 Set head selection to 1 (second head) call sub_0dech ;0e77 Call format track operation for head 1 ret nc ;0e7a Return if head 1 format failed l0e7bh: ; Advance to next track ld a,(01225h) ;0e7b Load current track number inc a ;0e7e Increment to next track (0→1→2...→76) ld (01225h),a ;0e7f Store updated track number cp 04dh ;0e82 Compare with 77 (0x4D = total tracks to format) jr c,l0e62h ;0e84 Continue formatting if more tracks remain jp sub_0b1ch ;0e86 Final drive validation read after complete format ;============================================================================== ; SYSTEM DIAGNOSTIC AND HARDWARE TEST SUITE (sub_0e89h) - 0x0E89-0x0EA1 ;============================================================================== ; Purpose: Comprehensive system hardware testing and validation ; Called by: System initialization to verify all hardware components ; ; Test Sequence: ; 1. RAM memory boundary detection and testing ; 2. Extended system component validation ; 3. FDC initialization and drive testing ; 4. Additional hardware subsystem verification ; ; Returns: Various status codes from individual test routines ;============================================================================== sub_0e89h: call sub_0ea2h ;0e89 Call RAM memory diagnostic test call nz,sub_0f6bh ;0e8c If RAM test indicates issues, call error handler call sub_0ecch ;0e8f Call extended system component test call nz,sub_0f70h ;0e92 If system test fails, call failure handler call sub_0a8dh ;0e95 Call FDC initialization and drive setup call nc,sub_0f75h ;0e98 If FDC init fails, call initialization error handler call sub_0f10h ;0e9b Call additional hardware subsystem test call nz,sub_0f7ah ;0e9e If hardware test fails, call diagnostic error handler ret ;0ea1 Return from complete system diagnostic suite ;============================================================================== ; RAM MEMORY DIAGNOSTIC TEST (0x0EA2) ;============================================================================== ; Purpose: Test available RAM and detect memory boundaries ; Tests RAM starting from 0x1400 (above 1KB base RAM) to find additional memory ; ; Memory Layout: ; - 0x0000-0x0FFF: EPROM ; - 0x1000-0x13FF: Base 1KB RAM (1024 bytes) ; - 0x1400+: Extended RAM (if present) or memory-mapped I/O ; ; Test Method: ; - Starts at 0x1400 (beyond base 1KB RAM) ; - Tests each location with multiple bit patterns ; - Continues until test fails (indicating no more RAM or different hardware) ; ; Purpose: Detect extended RAM modules or memory-mapped peripherals ; Returns: Z flag clear when memory boundary reached, Z set if wraps to 0x0000 ;============================================================================== sub_0ea2h: ld de,l0000h ;0ea2 Set DE = 0x0000 (used for wrap-around detection) ld hl,01400h ;0ea5 Start at 0x1400 (beyond 1KB base RAM) ; Test each memory location above base RAM l0ea8h: call sub_0eb3h ;0ea8 Test current memory location with bit patterns ret nz ;0eab Return when memory test fails (found boundary) inc hl ;0eac Move to next higher memory address sbc hl,de ;0ead Check if wrapped around to 0x0000 add hl,de ;0eaf Restore HL value jr nz,l0ea8h ;0eb0 Continue until boundary found or wrap-around ret ;0eb2 Return if wrapped to 0x0000 (full 64K RAM) ;============================================================================== ; MEMORY LOCATION TEST WITH MULTIPLE PATTERNS (0x0EB3) ;============================================================================== ; Purpose: Test single memory location with all bit patterns from test table ; Input: HL = memory address to test ; ; Test Procedure: ; 1. Load test pattern count and pattern table pointer ; 2. For each pattern: save original data, write pattern, read back, verify ; 3. Restore original data, test next pattern ; 4. Interrupts disabled during write/read/verify to prevent corruption ; ; Test Patterns (at l0ec9h): ; - 0x02: Tests bit 1 (and others as 0) ; - 0x55: Alternating bits pattern (01010101) ; - 0xAA: Inverse alternating pattern (10101010) ; ; Returns: Z flag set if all patterns pass, Z clear if any pattern fails ;============================================================================== sub_0eb3h: ld ix,l0ec9h ;0eb3 Point IX to test pattern table ld b,(ix+000h) ;0eb7 Load pattern count (first byte of table) ; Test each pattern from the table l0ebah: inc ix ;0eba Advance to next test pattern ld a,(ix+000h) ;0ebc Load test pattern into A ld c,(hl) ;0ebf Save original memory contents in C di ;0ec0 Disable interrupts (critical memory test section) ld (hl),a ;0ec1 Write test pattern to memory cp (hl) ;0ec2 Read back and compare with expected pattern ld (hl),c ;0ec3 Restore original memory contents ei ;0ec4 Re-enable interrupts ret nz ;0ec5 Return with error if pattern didn't match djnz l0ebah ;0ec6 Test next pattern (decrement B, loop if not zero) ret ;0ec8 Return with Z set (all patterns passed) ;============================================================================== ; MEMORY TEST PATTERN TABLE (0x0EC9) ;============================================================================== ; Format: [Count] [Pattern1] [Pattern2] [Pattern3] ; These patterns test different failure modes: ; - 0x02: Tests if bit 1 can be set while others stay clear ; - 0x55: Tests alternating bit pattern (detects adjacent bit interference) ; - 0xAA: Inverse alternating (detects stuck bits and crosstalk) ;============================================================================== l0ec9h: defb 0x03 ;0ec9 Number of test patterns defb 0x55 ;0eca Test pattern 1: 01010101 (alternating bits) defb 0xAA ;0ecb Test pattern 2: 10101010 (inverse alternating) ;============================================================================== ; INTERRUPT VECTOR TABLE INITIALIZATION (0x0ECC) ;============================================================================== ; Purpose: Set up interrupt vector table and perform peripheral testing ; This routine initializes the interrupt mode 2 vector table with error ; handlers and tests peripheral chips through port operations. ; ; Interrupt Vector Setup: ; Sets addresses 0x1330, 0x1332, 0x1334, 0x1336 to point to l0f3fh ; These are interrupt vector table entries for IM2 mode interrupts ; ; Peripheral Testing: ; Tests ports 0xF4 through 0xF7 with specific control sequences ; Uses port commands 0x30 (initialize) and 0x03 (test/verify) ; Validates peripheral response through status flag at 0x1103 ;============================================================================== sub_0ecch: ld hl,l0f3fh ;0ecc ; Load address of interrupt error handler ld (01330h),hl ;0ecf ; Set interrupt vector table entry 0 ld (01332h),hl ;0ed2 ; Set interrupt vector table entry 1 ld (01334h),hl ;0ed5 ; Set interrupt vector table entry 2 ld (01336h),hl ;0ed8 ; Set interrupt vector table entry 3 ld c,0f4h ;0edb ; Start with port 0xF4 (first peripheral port) ld a,030h ;0edd ; Load initialization command (0x30) out (c),a ;0edf ; Send initialization command to peripheral ;============================================================================== ; PERIPHERAL PORT TESTING LOOP (0x0EE1) ;============================================================================== ; Purpose: Test peripheral chips at ports 0xF4-0xF7 for proper response ; Tests each port with initialization and verification commands ;============================================================================== l0ee1h: ld a,0ffh ;0ee1 ; Set error flag (assume failure initially) ld (01103h),a ;0ee3 ; Store error flag in status location call sub_0f01h ;0ee6 ; Send command sequence to current peripheral push bc ;0ee9 ; Save current port number ld bc,01900h ;0eea ; Load delay count (6400 cycles for peripheral response) call sub_0f0ah ;0eed ; Wait for peripheral to process command pop bc ;0ef0 ; Restore current port number ld a,003h ;0ef1 ; Load verification command (0x03) out (c),a ;0ef3 ; Send verification command to peripheral ld a,(01103h) ;0ef5 ; Read status flag after peripheral operation or a ;0ef8 ; Test if peripheral responded correctly (0=success) ret nz ;0ef9 ; Return if peripheral failed to respond inc c ;0efa ; Move to next peripheral port (0xF4→0xF5→0xF6→0xF7) ld a,c ;0efb ; Check current port number cp 0f8h ;0efc ; Compare with end limit (0xF8 = beyond 0xF7) jr nz,l0ee1h ;0efe ; Continue testing if more ports remain ret ;0f00 ; Return with success (all peripherals tested) ;============================================================================== ; PERIPHERAL COMMAND SEQUENCE (0x0F01) ;============================================================================== ; Purpose: Send specific command sequence to peripheral chip ; Sends initialization commands to configure peripheral for testing ;============================================================================== sub_0f01h: ld a,028h ;0f01 ; Load parameter value (0x28 = timing/mode setting) ld b,087h ;0f03 ; Load command value (0x87 = control command) out (c),b ;0f05 ; Send control command to peripheral out (c),a ;0f07 ; Send parameter value to peripheral ret ;0f09 ; Return after command sequence complete ; -------------------------------------------------- ; sub_0f0ah: Wait/Delay Loop ; Burns CPU cycles by decrementing BC until it reaches zero. ; Used for timing delays, hardware settling, or pacing init steps. ; Entry: BC = delay value ; Exit: BC = 0 ; No hardware interaction, pure software delay ; -------------------------------------------------- sub_0f0ah: dec bc ;0f0a ld a,c ;0f0b or b ;0f0c jr nz,sub_0f0ah ;0f0d ret ;0f0f ; -------------------------------------------------- ; sub_0f10h: Hardware Initialization & Memory Test Routine ; - Clears accumulator and sets 01204h to 0 ; - Sets up pointer at 0133ch to l0f48h ; - Sets 01103h to 0xFF (error/status flag) ; - Calls setup_peripherals_01a1h with l0f55h (hardware setup) ; - Waits using delay loop (sub_0f0ah, BC=0x1000) ; - If 01103h is nonzero, returns (error) ; - If zero, compares 256 bytes at HL and DE (memory test), returns if mismatch ; Called at 0e9b as part of system initialization/test sequence ; -------------------------------------------------- ;============================================================================== ; MEMORY TEST AND HARDWARE INITIALIZATION (0x0F10) ;============================================================================== ; Purpose: Comprehensive RAM test comparing ROM shadow with actual RAM ; This routine performs a critical memory integrity test by comparing the ; first 256 bytes of ROM (0x0000-0x00FF) with corresponding RAM locations ; (0x1000-0x10FF) to verify RAM is functioning correctly. ; ; Test Strategy: ; 1. Initialize hardware peripherals and interrupt handlers ; 2. Set up error detection mechanisms ; 3. Allow hardware to stabilize with timing delay ; 4. Perform byte-by-byte comparison between ROM and RAM ; 5. Return status indicating memory integrity ; ; Memory Locations Used: ; • 0x1204: Test control flags (0=test mode, 1=normal operation) ; • 0x133C: Interrupt vector pointer (set to 0x0F48) ; • 0x1103: Error status flag (0xFF=error, 0x00=success) ; ; Hardware Integration: ; • Configures peripheral hardware via setup_peripherals_01a1h ; • Sets up interrupt handling for test environment ; • Uses timing delays to ensure hardware stability ; ; Returns: ; • Zero flag set: Memory test passed, RAM integrity verified ; • Zero flag clear: Memory test failed, RAM fault detected ;============================================================================== sub_0f10h: xor a ;0f10 ; Clear accumulator (A = 0) ld (01204h),a ;0f11 ; Set test control flag to 0 (enable test mode) ld hl,l0f48h ;0f14 ; Load address of interrupt service routine ld (0133ch),hl ;0f17 ; Set interrupt vector pointer for test environment dec a ;0f1a ; Set A = 0xFF (error flag value) ld (01103h),a ;0f1b ; Initialize error status to 0xFF (assume error initially) ld hl,l0f55h ;0f1e ; Load address of hardware configuration data call setup_peripherals_01a1h ;0f21 ; Initialize peripheral hardware and interrupts ld bc,01000h ;0f24 ; Load delay count (4096 iterations for hardware stabilization) call sub_0f0ah ;0f27 ; Execute timing delay loop (allow hardware to settle) ld a,(01103h) ;0f2a ; Read error status flag after hardware initialization or a ;0f2d ; Test if error flag is non-zero ret nz ;0f2e ; Return immediately if hardware initialization failed ;============================================================================== ; RAM INTEGRITY TEST - ROM vs RAM COMPARISON (0x0F2F) ;============================================================================== ; Performs byte-by-byte comparison between ROM (0x0000-0x00FF) and ; RAM (0x1000-0x10FF) to verify RAM is correctly mirroring ROM data. ; This test validates that the memory system is functioning properly. ;============================================================================== ld hl,01000h ;0f2f ; Point to start of RAM test area (0x1000) ld de,l0000h ;0f32 ; Point to start of ROM reference area (0x0000) ld b,0ffh ;0f35 ; Set counter for 255 bytes (256 total with DJNZ behavior) l0f37h: ld a,(de) ;0f37 ; Load byte from ROM (reference data) cp (hl) ;0f38 ; Compare with corresponding byte in RAM ret nz ;0f39 ; Return immediately if mismatch found (memory fault) inc hl ;0f3a ; Move to next RAM address inc de ;0f3b ; Move to next ROM address djnz l0f37h ;0f3c ; Continue until all 256 bytes tested ret ;0f3e ; Return with zero flag set (test passed) ;============================================================================== ; INTERRUPT SERVICE ROUTINE - ERROR HANDLER (0x0F3F) ;============================================================================== ; Purpose: Generic interrupt service routine for error handling during hardware tests ; This routine is installed in multiple interrupt vector table entries to catch ; any unexpected interrupts that occur during hardware initialization and testing. ; ; Called from: Interrupt vector table entries at 0x1330, 0x1332, 0x1334, 0x1336 ; Used during: Hardware initialization, FDC operations, and system testing ; ; Operation: ; 1. Save processor state (AF register) ; 2. Clear error status flag (mark as successful) ; 3. Restore processor state ; 4. Return from interrupt with interrupts enabled ; ; Function: Provides safe interrupt handling during critical hardware operations ; This prevents system crashes if unexpected interrupts occur during testing. ;============================================================================== l0f3fh: push af ;0f3f ; Save accumulator and flags on stack ;============================================================================== ; INTERRUPT COMPLETION HANDLER (0x0F40) ;============================================================================== ; Purpose: Common completion path for interrupt service routines ; Clears error status and returns from interrupt with proper state restoration. ;============================================================================== l0f40h: xor a ;0f40 ; Clear accumulator (A = 0) ld (01103h),a ;0f41 ; Clear error status flag (0 = success, no error) pop af ;0f44 ; Restore accumulator and flags from stack ei ;0f45 ; Enable interrupts (standard RETI behavior) reti ;0f46 ; Return from interrupt (pops PC and restores state) ;============================================================================== ; SPECIALIZED INTERRUPT HANDLER WITH PORT OPERATIONS (0x0F48) ;============================================================================== ; Purpose: Interrupt service routine that performs port I/O operations ; This appears to be a hardware-specific interrupt handler that sends data ; to port 0xFC during interrupt processing, possibly for peripheral control. ; ; Port Operations: ; • Sends 0xC3 to port 0xFC six times in sequence ; • Port 0xFC likely controls DMA, FDC, or other peripheral hardware ; • Multiple writes may be required for hardware sequencing ; ; Used by: Hardware initialization routine (pointed to by interrupt vector) ; Context: Called during peripheral setup and hardware testing phases ;============================================================================== l0f48h: push af ;0f48 ; Save accumulator and flags push bc ;0f49 ; Save BC register pair ld a,0c3h ;0f4a ; Load control value 0xC3 for port operation ld b,006h ;0f4c ; Set counter for 6 iterations l0f4eh: out (0fch),a ;0f4e ; Send DMA command 0xC3 to Z80 DMA controller ; ; 0xC3 = DMA reset/initialization command ; ; Repeated 6 times for proper DMA controller reset djnz l0f4eh ;0f50 ; Repeat 6 times (decrement B, loop if not zero) pop bc ;0f52 ; Restore BC register pair jr l0f40h ;0f53 ; Jump to common interrupt completion routine ;============================================================================== ; HARDWARE CONFIGURATION DATA TABLE (0x0F55) ;============================================================================== ; Purpose: Configuration data for peripheral hardware initialization ; Used by: setup_peripherals_01a1h routine during system initialization ; Format: Binary configuration data for DMA setup ; ; This table contains the initialization parameters and control sequences ; required to properly configure the Z80 peripheral hardware during boot. ; The data is processed by the hardware setup routine to configure: ; • Z80 DMA controller transfer parameters ; ; TABLE FORMAT: [byte_count] [port_address] [data_bytes...] ; • 0x13 (19 decimal) = total byte count for this configuration block ; • 0xFC = Z80 DMA controller port address ; • Following 19 bytes = DMA initialization sequence written to port 0xFC ;============================================================================== l0f55h: defb 0x13 ;0f55 Byte count: 19 bytes total (1 count + 18 DMA init bytes) defb 0xfc ;0f56 Target port: 0xFC (Z80 DMA controller) defb 0x79 ;0f57 DMA WR0: Base register, transfer mode (Block transfer, A→B) defb 0x00 ;0f58 DMA WR1: Port A starting address LOW byte defb 0x00 ;0f59 DMA WR2: Port A starting address HIGH byte defb 0xfe ;0f5a DMA WR0: Port A address LOW (0xFE = FDC data port region) defb 0x00 ;0f5b DMA WR1: Port A address HIGH byte defb 0x10 ;0f5c DMA WR2: Block length LOW byte (16 bytes) defb 0x14 ;0f5d DMA WR3: Block length HIGH + control defb 0xdb ;0f5e DMA WR4: Port B starting address LOW byte defb 0x00 ;0f5f DMA WR5: Port B starting address HIGH byte defb 0x10 ;0f60 DMA WR0: Port B address configuration defb 0x12 ;0f61 DMA WR1: Port B control (memory increment mode) defb 0x3c ;0f62 DMA WR2: Interrupt control and timing defb 0x82 ;0f63 DMA WR3: Interrupt vector base defb 0xcf ;0f64 DMA WR4: Pulse control (Ready/Wait signal timing) defb 0x05 ;0f65 DMA WR5: Command register (Enable DMA, continuous mode) defb 0xcf ;0f66 DMA WR6: Additional control flags defb 0xb3 ;0f67 DMA command: Load and enable DMA operation defb 0xab ;0f68 DMA command: Configure interrupt and ready modes defb 0x87 ;0f69 DMA command: Enable DMA transfer operation defb 0x00 ;0f6a Configuration terminator: 0x00 ;============================================================================== ; ERROR MESSAGE DISPLAY ROUTINES (0x0F6B-0x0F7F) ;============================================================================== ; Purpose: Display specific error messages for hardware failures ; These routines set HL to point to error message strings and call the ; standard print routine at l00fdh to display them to the console. ; ; Error Messages: ; • sub_0f6bh: "MEM ERR" - Memory error detected ; • sub_0f70h: "FLOPPY CTC ERR" - Floppy controller CTC timing error ; • sub_0f75h: "FLOPPY NEC ERR" - NEC µPD765A FDC hardware error ; • sub_0f7ah: "DMA ERR" - Z80 DMA controller error (also sets drive flag) ;============================================================================== sub_0f6bh: ld hl,l0f85h ;0f6b ; Point to "MEM ERR" message jr l0f82h ;0f6e ; Jump to common print routine sub_0f70h: ld hl,l0f8fh ;0f70 ; Point to "FLOPPY CTC ERR" message jr l0f82h ;0f73 ; Jump to common print routine sub_0f75h: ld hl,l0fa0h ;0f75 ; Point to "FLOPPY NEC ERR" message jr l0f82h ;0f78 ; Jump to common print routine sub_0f7ah: ld a,001h ;0f7a ; Set error flag value ld (01204h),a ;0f7c ; Store in drive status location (mark DMA error) ld hl,l0fb1h ;0f7f ; Point to "DMA ERR" message l0f82h: jp l00fdh ;0f82 ; Call standard string print routine ;============================================================================== ; ERROR MESSAGE STRINGS (0x0F85-0x0FBA) ;============================================================================== ; Null-terminated error message strings displayed by the error routines above. ; Each message includes CR/LF for proper console formatting. ; ; Messages: ; • l0f85h: "MEM ERR" - Memory subsystem error ; • l0f8fh: "FLOPPY CTC ERR" - CTC timing error for floppy operations ; • l0fa0h: "FLOPPY NEC ERR" - NEC µPD765A FDC hardware error ; • l0fb1h: "DMA ERR" - Z80 DMA controller error ;============================================================================== l0f85h: ; "MEM ERR" message defb 0x4d ;0f85 'M' defb 0x45 ;0f86 'E' defb 0x4d ;0f87 'M' defb 0x20 ;0f88 ' ' defb 0x45 ;0f89 'E' defb 0x52 ;0f8a 'R' defb 0x52 ;0f8b 'R' defb 0x0d ;0f8c defb 0x0a ;0f8d defb 0x00 ;0f8e l0f8fh: defb 0x46 ;0f8f 'F' defb 0x4c ;0f90 'L' defb 0x4f ;0f91 'O' defb 0x50 ;0f92 'P' defb 0x50 ;0f93 'P' defb 0x59 ;0f94 'Y' defb 0x20 ;0f95 ' ' defb 0x43 ;0f96 'C' defb 0x54 ;0f97 'T' defb 0x43 ;0f98 'C' defb 0x20 ;0f99 ' ' defb 0x45 ;0f9a 'E' defb 0x52 ;0f9b 'R' defb 0x52 ;0f9c 'R' defb 0x0d ;0f9d defb 0x0a ;0f9e defb 0x00 ;0f9f l0fa0h: defb 0x46 ;0fa0 'F' defb 0x4c ;0fa1 'L' defb 0x4f ;0fa2 'O' defb 0x50 ;0fa3 'P' defb 0x50 ;0fa4 'P' defb 0x59 ;0fa5 'Y' defb 0x20 ;0fa6 ' ' defb 0x4e ;0fa7 'N' defb 0x45 ;0fa8 'E' defb 0x43 ;0fa9 'C' defb 0x20 ;0faa ' ' defb 0x45 ;0fab 'E' defb 0x52 ;0fac 'R' defb 0x52 ;0fad 'R' defb 0x0d ;0fae defb 0x0a ;0faf defb 0x00 ;0fb0 l0fb1h: defb 0x44 ;0fb1 'D' defb 0x4d ;0fb2 'M' defb 0x41 ;0fb3 'A' defb 0x20 ;0fb4 ' ' defb 0x45 ;0fb5 'E' defb 0x52 ;0fb6 'R' defb 0x52 ;0fb7 'R' defb 0x0d ;0fb8 defb 0x0a ;0fb9 defb 0x00 ;0fba l0fbbh: xor a ;0fbb Clear A register (A = 0) ld (01226h),a ;0fbc Clear drive control flags ld (01202h),a ;0fbf Set current drive number to 0 (start with drive A:) ld (01225h),a ;0fc2 Clear drive parameter/selector inc a ;0fc5 A = 1 ld (01227h),a ;0fc6 Enable drive operations (1 = enabled) call l0de0h ;0fc9 Initialize FDC and check drive status ld hl,01000h ;0fcc Set boot load address to 0x1000 l0fcfh: ld (01200h),hl ;0fcf Store DMA/buffer address for disk operations call l0dabh ;0fd2 Attempt to read boot sector from current drive jp c,01000h ;0fd5 ld hl,l0fe1h ;0fd8 call l00fdh ;0fdb jp l0294h ;0fde l0fe1h: defb 0x42 ;0fe1 'B' defb 0x4f ;0fe2 'O' defb 0x4f ;0fe3 'O' defb 0x54 ;0fe4 'T' defb 0x20 ;0fe5 ' ' defb 0x45 ;0fe6 'E' defb 0x52 ;0fe7 'R' defb 0x52 ;0fe8 'R' defb 0x0d ;0fe9 defb 0x0a ;0fea defb 0x00 ;0feb l0fec: ; VERSION STRING - Displayed during system initialization defb 0x56 ;0fec 'V' defb 0x65 ;0fed 'e' defb 0x72 ;0fee 'r' defb 0x20 ;0fef ' ' defb 0x31 ;0ff0 '1' l0ff1h: defb 0x2e ;0ff1 '.' defb 0x32 ;0ff2 '2' defb 0x78 ;0ff3 'x' defb 0x20 ;0ff4 ' ' defb 0x38 ;0ff5 '8' l0ff6h: defb 0x20 ;0ff6 ' ' defb 0x69 ;0ff7 'i' defb 0x6e ;0ff8 'n' defb 0x63 ;0ff9 'c' defb 0x68 ;0ffa 'h' l0ffbh: defb 0x0d ;0ffb defb 0x0a ;0ffc defb 0x0a ;0ffd defb 0x00 ;0ffe - String terminator for print routine defb 0xff ;0ffe FF