; Tandy 2000 HD 2.00.00 BIOS ; Disassembled and documented by Chuck Coffing ; Last updated 20120102 ; Assemble with nasm: nasm -f bin -o t2k_bios.bin t2k_bios.asm ; ; Tags: ; {TRM} Technical Reference Manual. ; {PR} Programmer's Reference. ; {?} Research question for myself. ; {ODD} Oddity; cruft or bug or unfinished feature? ; {FEAT} Possible new feature. ; {BUG} Probably a bug. ; ; Memory map: ; 0040e {?} segment of indirect area ; 00420 {?} font related ; 00422 Equipment list ; 00424 <<4 to get amount of (reliable) memory ; 00426 0 ; 00428 copy of [00424] ; 0042a 0 ; 0042c Segment of video buffer ; 00432 System diagnostic failed flags: ; 0x10 bad ROM checksum ; 0x20 bad RAM ; 00442 Boot disk number (0 = FD0, 2 = HD0, ...) ; 00444 Boot offset ; 00446 Boot segment ; 0044a {?} floppy related ; 00472 0 ; 00474 Segment of video buffer ; 00476 16 byte table of pointers to character fonts ; 00486 Address Control Register ; 00487 device power-on / reset byte ; 0048a remaining tries to boot from FD; initially 10 ; 0048b remaining tries to boot from HD; initially 10 ; 00500 Bottom of boot stack ; 00600 Top of boot stack ; 18000 number of 64k banks of detected good memory ; 18002 0 ; 18004 2 byte Checksum of 8k ROM; should be 0 ; 18006 failing memory: offset of first bad byte ; 18008 failing memory: segment of first bad byte ; 1800a failing memory: stored/expected byte (stored, read both 0 if ok) ; 1800b failing memory: read/actual byte (stored, read both 0 if ok) ; 1800c first canonical segment beyond end of known-good RAM ; 18020 {? 20 bytes of 0} ; 18040 current cursor position ; 18042 current text character attr ; 18043 current fill (scroll) character attr ; 18050 1000; disk related (maybe number of retries, or timeout?) ; 18060 offset where boot sector was placed ; 18062 segment where boot sector was placed ; 18064 offset where boot sector was placed ; 18066 segment where boot sector was placed ; 19000 FD interrupt handler ; 19002 status of last disk op ; 1902c FD param table ; 1903e {?} IO port indirection? ; 19040 {?} IO port indirection? ; 19042 {?} IO port indirection? ; 19044 {?} IO port indirection? ; 19046 ; 1a000 modified copy of HDROMImage {?} sum of something (see LFB2) ; 1a002 {?} length of something (see L10f5) ; 1a008 ; 1a016 ; 1a026 HD0 parameter table ; 1b000 boot sector ; f8000 character generator {TRM 68} ; fe000 - 0xfffff ROM {TRM 68}. ; ; IO ports: ; 0x00 - 0x7f PCS0 {TRM 47} ; 0x02 DMA multiplexer {TRM 49} ; 0x04 terminal count strobe (terminates DMA). FD {TRM 85} ; 0x30 8272 main status register ; 0x60, 62, 70, 72 interrupt controller {TRM 70} ; PCS2 odd bytes: address control register; event bytes: 9007 {TRM 63} ; ; Things to research: ; ; continue at ------- ; ; .isWriteChar - logic/comment seems wrong/ is 0x10 write char, or not? ; ; ; finish SetUpHDROM; param table; follow boot sector through ; ; doc meanings/offsets of RecordBootParams ; LFB2 ; finish font: line 1075 ; messages line 811 ; comment line 189- hardware detection ; ; What is ds=0x1a00? ; Seems to be used as an indirect area. ; ; What is at ds=0x1800? system status area? ; ; What is at ds=0x1900? Copy of some portion of BIOS, modified ; ; To verify: ; - High characters (128-255) have same font as low? ; ; Future features: ; - serial boot ; - tool to read revision port of mainboard {TRM 95} ; - tool to read stats of HiRes board {TRM 280} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BITS 16 ORG 0 CPU 186 ; CS = 0xfe00 ; BP = 0x1f6a or 0x1f7a or 0x1f8a or 0x1f9a StartOfBoot: cli ; Disable interrupts during mem test & system diagnostics ; Re-enabled right before PrintMemoryBanner. cld jmp short start nop ; {?} what prints these? ; Note that strings are terminated with 0xff db 'BOOT ROM version 02.00.00', 0x0d, 0x0a db 'Copyright 1983,84 Tandy Corp.', 0x0d, 0x0a db 'All rights reserved.', 0x0d, 0x0a, 0xff start: ; L56 mov ax, 0x50 mov ss, ax mov sp, 0x100 ; Stack starts at 0x00600 mov ax, 0x0 mov ds, ax mov word [0x8], iretInstr ; NMI interrupt vector mov [0xa], cs ; ;; Set up 8237 DMA controller mov al, [cs:bp+0x5] ; in release builds, al <- 0x10 mov dx, 0x0 out dx, al ; refresh clock gate on {TRM appendix C} mov al, 0xb4 mov dx, 0x46 out dx, al ; 8253 PIT Load Mode Word {TRM appendix C} nop nop mov al, 0x1f mov dx, 0x44 out dx, al ; 8253 PIT Load Counter 2 {TRM appendix C} nop nop mov al, 0x0 mov dx, 0x44 out dx, al ; 8253 PIT Load Counter 2 {TRM appendix C} nop nop ;; Detect amount of memory cld mov bh, 0xe ; At most 14 banks (=896k) supported. TRM says 784k ; max, but Envision Designs sold a board supporting 896k. mov bl, 0x0 ; but zero 64k banks detected so far. mov ax, 0x0 mov ds, ax mov si, 0x0 .detectAnother64k: mov ax, 0x5a5a mov [si], ax ; Write 0x5a5a to ds:0 mov cx, 0x3e8 .delay1: loop .delay1 ; delay 1000*125ns = 125us cmp ax, [si] ; Did memory hold 0x5a5a for 125us? jne .memorySized not ax ; Invert, and test again, to be sure mov [si], ax mov cx, 0x3e8 .delay2: loop .delay2 cmp ax, [si] ; Did memory hold 0xa5a5? jne .memorySized mov ax, ds ; Yes, so... add ax, 0x1000 ; ...move to next 64k. mov ds, ax inc bl ; Note another bank of RAM. cmp bl, bh ; Have we hit the max supported memory? jb .detectAnother64k .memorySized: cmp bl, 0x2 ; Detected >= 128k? jae .memoryCorrectlySized mov bl, 0x2 ; T2K shipped with minimum 128k on mainboard, so assume that. .memoryCorrectlySized: mov bh, bl ; Remember # installed 64k banks, in BH ;; Memory test mov bl, 0x0 mov ax, 0x0 mov ds, ax mov si, 0xc ; For first bank, do not mov cx, 0x7ffa ; overwrite first 3 interrupt vectors. jmp short .setupPattern .setupNextTest: mov si, 0x0 ; All other banks get mov cx, 0x8000 ; completely overwritten. .setupPattern: mov dx, 0x5a5a .loop: mov [si], dx ; Write 0x5a5a out... nop ; ...wait... lodsw ; ...load back into AX... cmp ax, dx ; ...and verify. jne .testFailed inc dl ; Vary test pattern high... dec dh ; ...and low. nop nop loop .loop mov ax, ds ; Success; move to next 64k. add ax, 0x1000 mov ds, ax inc bl ; Note another good bank of RAM. cmp bl, bh ; Ran out of banks to test? jb .setupNextTest ; No; test next. jmp short .done .testFailed: cmp bl, 0x2 ; Failed in first 2 banks? jae .findBadByte mov bl, 0x2 ; Oh well... need 128k, so allow and hope. .findBadByte: dec si ; Back up to failed word. mov cl, dh ; DX is expected, mov ch, ah ; AX is actual. cmp al, dl ; Was low byte correct? je .done ; Yes, so high must be bad (SI points, CX compares) dec si ; Low byte is bad; SI points, mov cl, dl ; CX compares (CL expected, AL actual). mov ch, al ; .done: mov al, [cs:bp+0x1] ; Hard-coded max # of banks cmp bl, al jbe .doneCapped mov bl, al ; Enforce cap .doneCapped: and bl, 0xfe ; Clear low bit (upgrades come in 128k, so fail in 128k chunks) mov bh, 0x0 ; No longer care about # physical banks. mov di, bx ; DI is final # banks of good RAM (>=2) ;; some hardware init mov ax, [cs:bp+di+0x2] ; Get byte for ACR and device reset mov dx, 0x101 out dx, al ; Address Control Register {TRM appendix C, 280} mov al, ah mov dx, 0x0 out dx, al ; Power up / reset devices ;; Save memory diags, etc mov dx, ds mov ax, 0x1800 mov ds, ax mov ax, 0x0 mov es, ax mov al, [cs:bp+0x0] ; Index of hardware profile; usually 3 mov [es:0x420], al ; Save hardware profile index for later; configures fonts mov bh, 0x0 ; {ODD BH is already 0} mov [0x0], bx ; [0x18000] <- # good 64k banks mov di, bx ; {ODD DI is already # good banks} mov ax, [cs:bp+di+0x2] ; Get byte for ACR again mov [es:0x486], al ; Address Control Register mov [es:0x487], ah mov word [es:0x432], 0x0 ; System diagnostic defaults to good. mov [0x6], si ; Offset of byte of bad memory mov [0x8], dx ; Segment of byte of bad memory mov [0xa], cl ; stored/expected byte (no bad mem? cl=ch=0) mov [0xb], ch ; read/actual byte (no bad mem? cl=ch=0) mov ax, si shr ax, 0x4 add ax, dx mov [0xc], ax ; Canonical segment of first address beyond known-good RAM cmp ax, 0x2000 jae .enoughGoodRam mov ax, 0x2000 jmp short .badRam .enoughGoodRam: test ax, 0x1fff jz .multipleOf128KOk and ax, 0xe000 ; Round down to prior multiple of 128k jmp short .badRam .multipleOf128KOk: cmp si, byte +0x0 ; {BUG si==0 is not the most correct test of all mem good} jz .goodRam .badRam: or word [es:0x432], 0x20 ; Fail system diagnostic due to bad RAM in lowest 128k .goodRam: mov [es:0x424], ax ; Amount of (reliable) memory (>>4) mov word [es:0x426], 0x0 mov [es:0x428], ax sub ax, 0x140 ; -5k mov word [es:0x472], 0x0 ; mov [es:0x474], ax ; Video segment buffer mov word [es:0x42a], 0x0 mov [es:0x42c], ax ;; Checksum the ROM mov si, 0x0 mov cx, 0x1000 xor ax, ax .loopChecksum: add al, [cs:si] inc si add ah, [cs:si] inc si loop .loopChecksum mov [0x4], ax ; [0x18004] = checksum of all 8k of ROM or ax, ax jz .finishedRomChecksum ; {? is there a byte somewhere to compensate, to make it 0?} or word [es:0x432], 0x10 ; Fail system diagnostic due to nonzero checksum of ROM .finishedRomChecksum: ;; Detect hi-res board mov ax, 0x0 mov ds, ax mov dx, 0x180 in al, dx ; Hi-res board status {TRM 281} mov cl, 0x28 ; Default equipment list: {PR 233} mov ch, 0x21 ; FD1, reserved, BW monitor, joysticks cmp al, 0xff ; No response on this IO port? je .doneDetectingHiRes test al, 0x1 ; have HiRes board? (0=yes) jz .configHiResPalette or cl, 0x1 ; no HiRes: monochrome graphics option {PR 233} or ch, 0x4 ; reserved {PR 233} jmp short .doneDetectingHiRes .configHiResPalette: push ax ; See {TRM 280} mov dx, 0x198 ; low-intensity background: mov al, 0x0 ; black out dx, al mov dx, 0x19a ; low-intensity character: mov al, 0xf ; white out dx, al mov dx, 0x19c ; hi-intensity background: mov al, 0x0 ; black out dx, al mov dx, 0x19e ; hi-intensity character: mov al, 0x7 ; white out dx, al pop ax test al, 0x20 ; HiRes status bit: "future use" {TRM 281} jnz .hiResFutureBit test al, 0x2 ; HiRes status bit: jnz .plane0Only ; 3 planes installed? or cl, 0x2 ; monochrome graphics option {PR 233} {ODD} jmp short .doneProbingHiRes .plane0Only: or cl, 0x4 ; mono with color option {PR 233} jmp short .doneProbingHiRes .hiResFutureBit: or cl, 0x6 ; mono + mono with color {PR 233} .doneProbingHiRes: or ch, 0x2 ; color {PR 233} .doneDetectingHiRes: mov [0x422], cx ; Set equipment list ;; Default all remaining interrupts to be ignored mov ax, cs mov ds, ax mov ax, 0x0 mov es, ax cld mov di, 0xc ; First 3 are already set. mov cx, 0xfd .setDefaultIntHandlers: mov ax, iretInstr stosw mov ax, 0xfe00 stosw loop .setDefaultIntHandlers ;; Patch up interrupts from patch table mov si, IntPatchTable nop .patchInts: lodsw ; Load offset to change in IDT cmp ax, 0xffff jz .donePatchingInts mov di, ax movsw ; Patch IDT with offset of handler jmp short .patchInts .donePatchingInts: ;; Init some hardware mov ax, cs mov ds, ax mov si, ProgramFoo1 nop call OutPorts mov si, ProgramFoo2 nop call OutPorts mov si, ProgramFoo3 nop call OutPorts ;; Load character fonts mov ax, cs mov es, ax mov bx, CharSet8x8 ; 128 chars * 8x8 cells = 1024 = 0x400 bytes nop mov al, 0x1 ; Set char font, for 0-127 8x8 mov ah, 0x10 ; Get/set char font int 82 ; Video interrupt mov bx, CharSet8x8 nop mov al, 0x3 ; Set char font, for 128-255 8x8 mov ah, 0x10 ; Get/set char font int 82 ; Video interrupt mov bx, CharSet8x16 ; 128 chars * 8x16 cells = 2048 = 0x800 bytes nop mov al, 0x5 ; Set char font, for 0-127 8x16 mov ah, 0x10 ; Get/set char font int 82 ; Video interrupt mov bx, CharSet8x16 nop mov al, 0x7 ; Set char font, for 128-255 8x16 mov ah, 0x10 ; Get/set char font int 82 ; Video interrupt ;; Clear screen mov ax, 0x1800 mov ds, ax mov bl, 0xa ; foreground color call PrintFormFeed ;; Program the video card mov ax, cs mov ds, ax mov si, Program9007 nop call OutPorts ;; cld mov ax, cs mov ds, ax ; {ODD useless to set DS for stosw; DS also set below} mov ax, 0x1800 mov es, ax mov ax, 0x0 mov di, 0x20 mov cx, 0xa ; Zero out ten words: rep stosw ; memset(0x18020, 0, 20) ;; sti call PrintMemoryBanner ;; call Delay ; {? Probably gives HD more time to spin up} mov ax, 0x1800 mov ds, ax mov ax, 0x0 mov es, ax mov word [0x2], 0x0 ; [18002] <- 0x0 mov byte [es:0x48a], 0xa ; 10 retries to read from FD at boot mov byte [es:0x48b], 0xa ; 10 retries to read from HD at boot push ds push es call BootFromFD pop es pop ds jc .fdFailedTryHd mov al, 0x0 ; booted from FD0 call .goodBoot .fdFailedTryHd: push ds push es call BootFromHD pop es pop ds jc .hang mov al, 0x2 ; booted from HD0 call .goodBoot .hang: ; {FEAT print failure to explain hang} jmp short .hang .goodBoot: push ds push es mov [es:0x442], al ; Note FD vs HD boot mov ax, [0x64] ; Get offset of boot sector mov [es:0x444], ax ; ...save to standard BIOS area. mov ax, [0x66] ; Get segment of boot sector (0x1b00) mov [es:0x446], ax ; ...save to standard BIOS area. mov es, ax call far [0x64] ; Call bootsector. Will hang if it returns. pop es ; {FEAT print failure to explain hang} pop ds ret errRet: ; L331 jmp short stcAndRet ; {ODD What's the point of this?} stcAndRet: ; L333 stc jmp short andRet clcAndRet: ; L336 clc andRet: ret ; Note: DS = 0x1800 RecordBootParams: mov [0x50], cx ; {ODD nothing uses this?} mov [0x52], cx ; {ODD nothing uses this?} mov word [0x64], 0x0 ; Offset of boot sector mov word [0x66], 0x1b00 ; Segment of boot sector mov word [0x60], 0x0 ; Offset of boot sector {ODD BootFromFD sets 60 but .goodBoot reads 64} mov word [0x62], 0x1b00 ; Segment of boot sector ret BootFromFD: ; L359 mov cx, 0x3e8 ; {ODD stuffed into [0x50] but not used} call RecordBootParams call SetUpFDROM .retry: mov dl, 0x0 ; use FD not HD mov ah, 0x0 ; Reset floppy disk int 86 ; Int86FDHD or ah, ah jnz .checkError mov dh, 0x0 ; head 0 mov dl, 0x0 ; use FD not HD; FD#0 mov ch, 0x0 ; cylinder 0 mov cl, 0x1 ; sector 1 mov al, 0x1 ; 1 sector les bx, [0x60] ; Where to put data mov ah, 0x2 ; Read sector(s) from floppy disk int 86 ; Int86FDHD or ah, ah ; read ok? jz .ok dec byte [es:0x48a] ; consumed a retry jnz .retry jmp short .badRead nop .ok: cmp al, 0x1 ; read the 1 sector requested? jnz .badRead jmp short clcAndRet .checkError: test ah, 0x7f jnz .badRead ; ok? jmp short stcAndRet ; error! .badRead: jmp short errRet BootFromHD: ; L39B mov cx, 0x3e8 ; {ODD stuffed into [0x50] but not used} call RecordBootParams call SetUpHDROM .retry: mov dl, 0x80 ; use HD not FD mov ah, 0x0 ; Reset int 86 ; Int86FDHD or ah, ah jnz .fail mov dh, 0x0 ; head 0 mov dl, 0x80 ; use HD not FD mov ch, 0x0 ; cylinder 0 mov cl, 0x1 ; sector 1 mov al, 0x1 ; read 1 sector les bx, [0x60] ; Where to put data mov ah, 0x2 ; Read sector(s) int 86 ; Int86FDHD or ah, ah jz .ok dec byte [es:0x48b] ; consumed a retry jnz .retry jmp short .fail nop .ok: cmp al, 0x1 ; Expect al == 1, or... jnz .fail ; error! jmp clcAndRet ; success jmp stcAndRet ; {ODD how can anything get here?} error! .fail: jmp errRet iretInstr: ; L3DB iret ;; Common interrupt handling routines; see patch table at L82C ;L3DC: ; {? unused?} push ax mov ax, 0x1 jmp short L3FE Int0DivideError: ; L3E2 push ax mov ax, 0x2 jmp short L3FE IntSystemTimer: ; L3E8 push ax mov ax, 0x4 jmp short L3FE L3EE: ; {? unused?} push ax mov ax, 0x8 jmp short L3FE L3F4: push ax mov ax, 0x40 jmp short L3FE L3FA: push ax mov ax, 0x80 L3FE: push ds push bx mov bx, 0x0 mov ds, bx or [0x432], ax ; {? setting system diagnostic flag, because ; unexpected int during boot?} pop bx pop ds pop ax iret ;----------- sti push ds pusha call L487 popa pop ds iret sti push ds pusha call L48E popa pop ds iret sti push ds pusha mov si, 0x20 call L474 jz L42A L42A: call L49F popa pop ds iret sti push ds pusha mov si, 0x28 call L474 jz L43B L43B: call L487 popa pop ds iret Int118: ; L441 sti push ds pusha mov si, 0x2c call L474 jz L44C L44C: call L487 popa pop ds iret Int120: ; L452 sti push ds pusha mov si, 0x30 call L474 jz L45D L45D: call L48E popa pop ds iret Int121: ; L463 sti push ds pusha mov si, 0x32 call L474 jz L46E L46E: call L48E popa pop ds iret ; {? Seems like this is a common handler for ints; si differs} L474: mov ax, 0x1800 mov ds, ax mov ax, 0xffff jmp short .L481 mov ax, 0x0 .L481: nop nop nop or ax, ax ret L487: mov dx, 0x60 ; {TRM appendix C} 8259A-2 write command words mov al, 0x20 jmp short L493 L48E: mov dx, 0x70A ; {TRM appendix C} 8259A-2 write command words mov al, 0x20 L493: cli out dx, al ; {TRM appendix C} 8259A-2 write command words mov al, 0xb out dx, al ; {TRM appendix C} 8259A-2 write command words nop nop in al, dx or al, al jnz L4A7 L49F: cli mov dx, 0xff22 ; {? seems like a common way to finish ints?} mov ax, 0x8000 out dx, ax L4A7: sti ret Delay: ; L4AC mov bx, 0x3e8 .top: call .delay62us ; call 1000 times; ~62+ ms? dec bx jnz .top ret out dx, al ; {ODD Never executed?} .delay62us: mov cx, 0x1f4 ; 500 cycles * 125 nsec = ~62us .delay: loop .delay ret OutPorts: lodsb ; load length byte into al or al, al ; zero length? nevermind. jz short .done .one: dec al jnz .two lodsw mov dx, ax ; dx <- IO port lodsb ; al <- data for port out dx, al jmp short OutPorts .two: lodsw mov dx, ax ; dx <- IO port lodsw ; ax <- data for port out dx, ax jmp short OutPorts .done: ret ; length of data, 16-bit IO port, data ProgramFoo1: db 0x02, 0x28, 0xFF, 0xC0, 0x00 db 0x02, 0x2A, 0xFF, 0x07, 0x00 db 0x02, 0x38, 0xFF, 0x60, 0x00 db 0x02, 0x3A, 0xFF, 0x65, 0x00 db 0x02, 0x34, 0xFF, 0x02, 0x00 db 0x02, 0x36, 0xFF, 0x03, 0x00 db 0x02, 0x32, 0xFF, 0x07, 0x00 db 0x00 ProgramFoo2: db 0x01, 0x60, 0x00, 0x13 ; 8259A-2 / write command / db 0x01, 0x62, 0x00, 0x70 db 0x01, 0x62, 0x00, 0x0D db 0x01, 0x62, 0x00, 0xEB db 0x00 ProgramFoo3: db 0x01, 0x70, 0x00, 0x13 ; 8259A-2 / write command / db 0x01, 0x72, 0x00, 0x78 db 0x01, 0x72, 0x00, 0x0d db 0x01, 0x72, 0x00, 0xfc db 0x00 Program9007: db 0x01, 0x2c, 0x01, 0x00 ; 9007 / R16 / db 0x01, 0x2c, 0x01, 0x00 ; 9007 / R16 / db 0x01, 0x2c, 0x01, 0x00 ; 9007 / R16 / db 0x01, 0x2c, 0x01, 0x00 ; 9007 / R16 / db 0x01, 0x00, 0x01, 0x6a ; 9007 / R00 / db 0x01, 0x02, 0x01, 0x4f db 0x01, 0x04, 0x01, 0x10 db 0x01, 0x06, 0x01, 0x08 db 0x01, 0x08, 0x01, 0x08 db 0x01, 0x0a, 0x01, 0x21 db 0x01, 0x0c, 0x01, 0x52 db 0x01, 0x0e, 0x01, 0x18 db 0x01, 0x10, 0x01, 0x2f db 0x01, 0x12, 0x01, 0xb8 db 0x01, 0x14, 0x01, 0x6a db 0x01, 0x16, 0x01, 0x02 db 0x01, 0x18, 0x01, 0x00 db 0x01, 0x1a, 0x01, 0x36 db 0x01, 0x1c, 0x01, 0x00 db 0x01, 0x1e, 0x01, 0x00 db 0x01, 0x20, 0x01, 0xfe db 0x01, 0x22, 0x01, 0xfe db 0x01, 0x24, 0x01, 0xfe db 0x01, 0x26, 0x01, 0x00 db 0x01, 0x28, 0x01, 0x00 db 0x01, 0x2e, 0x01, 0x00 db 0x01, 0x30, 0x01, 0x00 db 0x01, 0x32, 0x01, 0x00 db 0x01, 0x34, 0x01, 0x00 db 0x01, 0x2a, 0x01, 0x00 db 0x01, 0x2a, 0x01, 0x00 db 0x01, 0x2a, 0x01, 0x00 db 0x01, 0x2a, 0x01, 0x00 db 0x00 PrintMemoryBanner: push ds push es mov ax, 0x1800 mov ds, ax mov ax, 0x0 mov es, ax mov ax, [es:0x432] ; Get system diagnostic (0 is good) or ax, ax jnz .badDiag mov bl, 0xa ; light green call PrintEmptyChar mov si, sMemorySize nop call PrintString mov si, [0x0] ; 0x18000 number 64k banks detected good sub si, byte +0x2 add si, si add si, s128k call PrintString ; Print memory size mov si, sKilobyteLabel nop call PrintString call PrintCRLFBeep jmp short .done .badDiag: mov bl, 0xa ; light green call PrintEmptyChar mov si, sSystemFailsDiag nop call PrintString call PrintCRLFBeep .lockup: jmp short .lockup .done: pop es pop ds ret PrintCRLFBeep: mov bl, 0xa ; light green call PrintEmptyChar mov si, sCRLF nop jmp short PrintString mov si, sBeep nop jmp short PrintString ; {ODD How to get here?} mov si, s2Spaces nop PrintString: ; L602 push ax push bx mov bl, 0xf ; Foreground color white .nextChar: mov al, [cs:si] inc si cmp al, 0xff ; string terminator? jz .endOfString call PrintChar jmp short .nextChar .endOfString: pop bx pop ax ret PrintEmptyChar: ; L616 push ax mov al, 0x0 ; {ODD Why print ascii 0 vs space?} call PrintChar pop ax ret PrintFormFeed: ; L61E mov al, 0xc ; formfeed PrintChar: ; L620 push ax mov ah, 0xe ; Write TTY int 82 ; Video interrupt pop ax ret ; {? how to get here?} mov al, bh call .L62E mov al, bl .L62E: push ax shr al, 0x4 call .L636 pop ax .L636: and al, 0xf cmp al, 0xa jc .L63E add al, 0x7 .L63E: add al, 0x30 push bx mov bl, 0xf call PrintChar pop bx ret sCRLF: ; L648 db 0x0d, 0x0a, 0xff sBeep: db 0x07, 0xff s2Spaces: db 0x20, 0x20, 0xff sMemorySize: ; L650 db 'Memory Size = ', 0xff s128k: db '128', 0xff db '256', 0xff db '384', 0xff db '512', 0xff db '640', 0xff db '768', 0xff ; {FEAT} Support 896k, as offered by the Evince board sKilobyteLabel: db 'K', 0xff sSystemFailsDiag: ; L679 db 'System Fails Diagnostic Test', 0xff ; ax = 0xe ; bl foreground color Int82Video: ; L696 push ds push es pusha mov bp, sp cmp ah, 0xe ; Write TTY? jne .isWriteChar call .writeTTY jmp short .done .isWriteChar: cmp ah, 0x10 ; Write Character? jne .done call GetSetCharFont .done: popa pop es pop ds iret .writeTTY: mov cx, 0x0 mov ds, cx mov es, [0x474] ; get video buffer segment mov cx, 0x1800 mov ds, cx mov ah, bl ; bl = foreground color and ah, 0xf cmp ah, 0xa jne .notFormFeed mov [0x42], bl ; save color cmp al, 0xc ; is form feed? jnz .notFormFeed mov [0x43], bl ; save fill color .notFormFeed: ; L6D5 mov ah, [0x42] ; get color mov bx, [0x40] ; get cursor position cmp al, 0x20 jnc .writeSpace cmp al, 0x7 je .writeBell cmp al, 0x8 je .writeBackspace cmp al, 0x9 je .writeTab cmp al, 0xa je .writeLineFeed cmp al, 0xc je .writeFormFeed cmp al, 0xd je .writeCarriageReturn .L6F9: jmp short .ret nop .writeSpace: call CalcRowColOffsetDi stosw inc bl jmp short .doneWriting .writeBell: call Bell jmp short .L6F9 .writeBackspace: cmp bl, 0x0 jz .L6F9 dec bl jmp short .doneWriting .writeTab: add bl, 0x8 and bl, 0xf8 jmp short .doneWriting .writeLineFeed: inc bh jmp short .doneWriting .writeFormFeed: mov bx, 0x0 call CalcRowColOffsetDi mov cx, 0x7d0 ; 25 rows * 80 cols mov al, 0x20 ; space mov ah, [0x43] ; get fill color rep stosw jmp short .doneWriting .writeCarriageReturn: mov bl, 0x0 .doneWriting: call CheckWrap mov [0x40], bx ; save new cursor position mov al, bh mov dx, 0x130 out dx, al ; {TRM appendix C} 9007 R18 mov al, bl mov dx, 0x132 ; {TRM appendix C} 9007 R19 out dx, al .ret: ; L746 ret CalcRowColOffsetDi: ; L747 push ax push bx mov di, 0x0 mov al, 0x50 mul bh ; ax = row *= 80 mov bh, 0x0 add ax, bx ; add column offset add ax, ax ; double due to character attrs add di, ax pop bx pop ax ret CheckWrap: ; L75B cmp bl, 0x50 ; Hit the 80th column? jc .checkRow mov bl, 0x0 ; Yes, back to 0 column, inc bh ; and down a line. .checkRow: cmp bh, 0x19 ; Hit the 25th row? jc .noScroll mov bh, 0x18 ; Yes, but stay where you are; call ScrollScreenUp ; and scroll. .noScroll: ret ScrollScreenUp: push ds push bx push es pop ds mov bl, 0x0 mov bh, 0x1 call CalcRowColOffsetDi mov si, di ; offset of 1, 0 mov bh, 0x0 call CalcRowColOffsetDi mov cx, 0x780 ; 24*80*2 rep movsw ; Copy from 1,0 to 0,0 mov cx, 0x50 mov al, 0x20 mov ah, [0x43] ; get fill color rep stosw ; fill last line pop bx pop ds ret Bell: ; {FEAT: umm... perhaps beep?} ret ; If setting, ES:BX points to character font ; If getting, ES:BX is set to current character font ; al bit 0: setting? ; al bits 1,2: which set GetSetCharFont: ; L795 mov cx, 0x0 mov ds, cx mov si, 0x476 push ax and ax, 0x6 add ax, ax add si, ax ; 0x476: 0-127 8x8, 0x47a: 128-255 8x8, 0x47c: 0-127 8x16, 0x480: 128-255 8x16 pop ax test al, 0x1 ; Change pointer to new character set? jnz .writePointerToChar mov bx, [si] mov es, [si+0x2] ; es:bx now points to character font mov [bp+0x8], bx mov [bp+0x10], es jmp short .out nop .writePointerToChar: ; L7B8 mov [si], bx mov [si+0x2], es ; save caller's es:bs pointer to character font test al, 0x4 ; 8x16 cell? jnz .is8x8Font jmp short .out nop .is8x8Font: ; L7C4 mov ah, [0x420] ; {?} video feature flags? determines where to put font mov si, bx mov bx, es mov ds, bx mov bx, 0xf800 ; ROM for fonts mov es, bx mov di, 0x0 mov cx, 0x800 cmp ah, 0x1 ja .L7E0 jz .L7EF .L7E0: test al, 0x2 jz .L7E8 add di, 0x1000 .L7E8: movsb inc di loop .L7E8 jmp short .out nop .L7EF: test al, 0x2 jz .L7F7 add di, 0x2000 .L7F7: push cx lodsb xor dl, dl mov cx, 0x8 .L7FE: shr al, 1 adc dl, dl loop .L7FE mov ax, di and ax, 0x3c shr ax, 0x2 xor bx, bx mov cx, 0x4 .L811: shr ax, 1 adc bx, bx loop .L811 shl bx, 0x2 mov ax, di and ax, 0xffc3 or bx, ax mov [es:bx], dl pop cx add di, byte +0x4 loop .L7F7 .out: ret ; {? Seems unused} iret ;; Patch table to fix up interrupt handling: ;; Words are alternating offset of IDT and offset of call in ROM IntPatchTable: ; L82C: db 0x00, 0x00, 0xe2, 0x03 ; 0: divide error L3E2 db 0x04, 0x00, 0xe2, 0x03 ; 1: single step L3E2 db 0x08, 0x00, 0xdb, 0x03 ; 2: NMI: iret L3DB db 0x0c, 0x00, 0xe2, 0x03 ; 3: breakpoint L3E2 db 0x10, 0x00, 0xe2, 0x03 ; 4: overflow L3E2 db 0x14, 0x00, 0xE2, 0x03 ; 5: print screen L3E2 db 0x18, 0x00, 0xE2, 0x03 ; 6: invalid op code L3E2 db 0x1C, 0x00, 0xE2, 0x03 ; 7: processor extention not available L3E2 db 0x28, 0x00, 0x49, 0x0D ; 9: hard disk? (or lpt2? vertical retrace?) LD49 db 0x2C, 0x00, 0x5E, 0x0D ; 10: COM2 LD5E db 0x20, 0x00, 0xE8, 0x03 ; 8: system timer L3E8 db 0x48, 0x00, 0xE8, 0x03 ; 18: Memory size {PR 234} L3E8 db 0x4C, 0x00, 0xE8, 0x03 ; 19: db 0xC8, 0x01, 0xE8, 0x03 ; 114: db 0xCC, 0x01, 0xE8, 0x03 ; 115: db 0xD0, 0x01, 0x16, 0x0C ; 116: db 0xD4, 0x01, 0x16, 0x0C ; 117: db 0xD8, 0x01, 0x41, 0x04 ; 118: db 0xDC, 0x01, 0xE8, 0x03 ; 119: db 0xE0, 0x01, 0x52, 0x04 ; 120: db 0xE4, 0x01, 0x63, 0x04 ; 121: db 0xE8, 0x01, 0xE8, 0x03 ; 122: db 0xEC, 0x01, 0xE8, 0x03 ; 123: db 0x48, 0x01, 0x96, 0x06 ; 82: video display Int82Video L696 db 0x40, 0x00, 0x96, 0x06 ; 16: video display Int82Video L696 db 0x58, 0x01, 0x1B, 0x09 ; 86: floppy disk {PR 194} Int86FDHD L91B db 0x4C, 0x00, 0x1B, 0x09 ; 19: floppy and hard disk {PR 194} Int86FDHD L91B db 0xFF, 0xFF ; marker for end of patch table SetUpFDROM: ; L89D pusha push ds mov ax, 0x1900 ; write to disk area... mov es, ax mov ax, 0xfe00 ; ...from ROM. mov ds, ax mov si, FDIntHandler nop mov di, 0x0 mov cx, 0x48 ; Copy int handler and param table. nop cld rep movsb ; Do the copy. mov ax, 0x0 mov ds, ax mov word [0x78], 0x2c ; int 1e: Update floppy disk parameter pointer {PR 194} mov word [0x7a], 0x1900 mov al, 0x0 out 0x2, al ; DMA control port: disable all {TRM appendix C} mov [0x44a], al ; mov [es:0x46], al pop ds popa ret FDIntHandler: ; L8D3 db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00 db 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xa2, 0x00, 0x00, 0x04 db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x16 FDParamTable: ; {Ralf Brown, Int 1E, Table 0929} db 0xe0, 0x8c, 0x00, 0x02, 0x09, 0x2a, 0xff, 0x50, 0xf6, 0x19, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; dl: FD or HD ; ah: command Int86FDHD: ; L91B sti push ds push es push bx push cx push ds push si push di push bp push dx mov bp, sp mov si, 0x1900 mov ds, si call .doDiskOp mov ah, [0x2] ; Get status of last disk op cmp ah, 0x1 cmc ; carry flag implies failure {PR 220} pop dx pop bp pop di pop si pop ds pop cx pop bx pop es pop ds retf 0x2 .doDiskOp: mov dh, al or ah, ah jz .resetDisks cmp ah, 0x1 jz .getLastDiskOpStatus mov byte [0x2], 0x0 ; Assume disk op will be successful cmp dl, 0x2 jnc .readSectorsFromHD ; {?} what is dl? cmp ah, 0x2 jnz .readSectorsFromHD jmp otherDiskOps .readSectorsFromHD: mov byte [0x2], 0x1 ; status of last disk op: Bad command ret .getLastDiskOpStatus: mov al, [0x2] ret .resetDisks: push ds mov ax, 0x0 mov ds, ax mov al, [0x487] ; pop ds and al, 0xdf ; mask off Refresh Clock Gate out 0x0, al ; {TRM appendix C} everything on mov cx, 0x14 .resetDisksDelay: loop .resetDisksDelay or al, 0x20 out 0x0, al ; {TRM appendix C} FDC reset mov al, 0x5 .L983: mov cx, 0x0 .resetDisksDelay2: loop .resetDisksDelay2 dec al jnz .L983 mov byte [0x2], 0x0 ; last disk op: success mov cx, 0x3c .L994: call LBD8 mov byte [0x0], 0x0 jnc .L9A4 .L99E: or byte [0x2], 0x20 ; last disk op: CRC error ret .L9A4: mov al, [0x37] cmp al, 0x80 jz .L9C3 test al, 0x2 jnz .L994 test al, 0x1 jnz .L9BA xor byte [0x3], 0xff jmp short .L9BF .L9BA: xor byte [0x5], 0xff .L9BF: loop .L994 jmp short .L99E .L9C3: mov ah, 0x3 call LB08 mov bx, 0x1 call LB36 mov bx, 0x3 call LB36 and byte [0x0], 0xfc mov dl, 0x0 mov ch, 0xa call LB4A jc .LA20 and byte [0x0], 0xfc mov ch, 0x0 call LB4A jc .LA20 mov ah, 0x4 call LB08 mov ah, 0x1 call LB08 call LC29 jc .LA20 mov ah, [0x37] and ah, 0x20 jz .LA17 mov dl, 0x1 mov ch, 0xa call LB4A and byte [0x0], 0xfc mov ch, 0x0 call LB4A .LA17: mov dl, 0x0 mov ch, 0x2 call LB4A jnc .LA26 .LA20: or byte [0x2], 0x40 ; last disk op: FDC failure ret .LA26: mov ah, 0x4a call LB08 mov ah, 0x0 call LB08 call LBF4 jnc .LA38 jmp .L99E .LA38: call LC29 jnc LA40 jmp .L99E LA40: cmp byte [0x3a], 0x2 jz LA4D mov byte [0x4], 0xff ret LA4D: mov byte [0x4], 0x0 ret otherDiskOps: call LBAB jnc LA60 mov byte [0x2], 0x9 ; {?} last disk op mov al, 0x0 ret LA60: call LB4A mov dh, 0x0 jc LAB9 push word 0xab9 nop mov ah, 0x66 call LB08 mov ah, [bp+0x1] shl ah, 0x2 and ah, 0x4 or ah, dl call LB08 mov ah, ch call LB08 mov ah, [bp+0x1] call LB08 mov ah, cl call LB08 mov bx, 0x7 call LB36 mov bx, 0x9 call LB36 mov bx, 0xb call LB36 mov bx, 0xd call LB36 mov bx, si pop si call LCDF jnc LAB6 or byte [0x2], 0x8 ; last disk op: DMA overrun jmp short LAFE nop LAB6: call LBF4 LAB9: jc LAFE call LC29 jc LAFD cld mov si, 0x37 lodsb and al, 0xc0 jz LB02 cmp al, 0x40 jnz LAF4 lodsb shl al, 1 mov ah, 0x4 jc LAF6 shl al, 0x2 mov ah, 0x10 jc LAF6 shl al, 1 mov ah, 0x8 jc LAF6 shl al, 0x2 mov ah, 0x4 jc LAF6 shl al, 1 mov ah, 0x3 jc LAF6 shl al, 1 mov ah, 0x2 jc LAF6 LAF4: mov ah, 0x20 LAF6: or [0x2], ah ; last disk op: call LC67 LAFD: ret LAFE: call LC29 ret LB02: call LC67 xor ah, ah ret ; {? FDC writing?} ; Writes ah to floppy LB08: push cx mov cl, 0x20 .delay: dec cl jnz .delay ; {? why not loop? why delay at all?} mov cx, 0x0 .notReadyToWrite: in al, 0x30 ; Read FDC status {TRM 85} and al, 0x40 ; I/O direction; 1 = FDC to CPU; 0 = CPU to FDC jz .readyToWrite loop .notReadyToWrite .timeout: or byte [0x2], 0x80 ; last disk op: timeout error stc pop cx pop ax ret .readyToWrite: mov cx, 0x0 .notReadyForData: in al, 0x30 ; Read FDC status {TRM 85} and al, 0x80 ; data ready? jnz .readyForData loop .notReadyForData jmp short .timeout .readyForData: mov al, ah out 0x32, al ; Write to FDC data register {TRM 85} pop cx ret LB36: push ds mov ax, 0x0 mov ds, ax push si lds si, [0x78] ; Floppy Disk Parameter Pointer {PR 194} shr bx, 1 mov ah, [bx+si] ; {?} Load ? from a table? pop si pop ds jc LB08 ret LB4A: mov al, 0x1 push cx mov cl, dl shl al, cl pop cx test [0x0], al jnz LB78 or [0x0], al mov ah, 0x7 call LB08 mov ah, dl call LB08 call LBD3 mov ah, 0x7 call LB08 mov ah, dl call LB08 call LBD3 jc LBAA LB78: mov ah, 0xf call LB08 mov ah, dl call LB08 mov ah, ch or byte [0x4], 0x0 jz LB8D shl ah, 1 LB8D: call LB08 call LBD3 pushf mov bx, 0x12 call LB36 push cx LB9B: mov cx, 0x226 or ah, ah jz LBA8 LBA2: loop LBA2 dec ah jmp short LB9B LBA8: pop cx popf LBAA: ret LBAB: mov si, 0x8 mov [si+0xc], es mov [si+0xa], bx mov ah, dh xor al, al shr ax, 1 push ax mov bx, 0x6 call LB36 mov bl, ah pop ax .LBC4: shl ax, 1 dec bl jnz .LBC4 mov bx, si mov [bx+0xe], ax call LC7E ret LBD3: call LBF4 jc LBEC LBD8: mov ah, 0x8 call LB08 call LC29 jc LBEC mov al, [0x37] and al, 0x60 cmp al, 0x60 jz LBED clc LBEC: ret LBED: or byte [0x2], 0x40 ; last disk op: seek error stc ret LBF4: sti pusha mov bl, 0xf xor cx, cx LBFA: test byte [0x0], 0x80 jnz LC0D loop LBFA dec bl jnz LBFA or byte [0x2], 0x80 ; last disk op: timeout error stc LC0D: pushf and byte [0x0], 0x7f popf popa ret sti Int116_117: ; LC16 push ds pusha mov ax, 0x1900 mov ds, ax or byte [0x0], 0x80 call L487 popa pop ds iret ; {? FDC reading?} LC29: mov di, 0x37 cld pusha mov bl, 0x7 ; LC30: xor cx, cx ; Retry loop 64k times! mov dx, 0x30 .loop: in al, dx ; Read FDC status {TRM 85} test al, 0x80 ; data ready ready for IO? jnz DataReady ; ready? loop .loop or byte [0x2], 0x80 ; last disk op: timeout error LC41: stc popa ret DataReady: ; LC44 in al, dx test al, 0x40 ; I/O direction; 1 = FDC to CPU; 0 = CPU to FDC jnz DataReadyFdcToCpu LC49: or byte [0x2], 0x20 ; last disk op: FDC failure jmp short LC41 DataReadyFdcToCpu: in al, 0x32 ; Read FDC data register {TRM appendix C} mov [di], al inc di mov cx, 0xf ; FDC must be serviced every 26 usec {TRM 86} .LC58: loop .LC58 in al, dx ; Read FDC status {TRM appendix C, 85} test al, 0x10 ; FDC read or write command in progress? jnz .LC61 popa ret .LC61: dec bl jnz LC30 jmp short LC49 LC67: mov al, [0x3a] cmp al, ch mov al, [0x3c] jz LC7B mov bx, 0x8 call LB36 mov al, ah inc al LC7B: sub al, cl ret LC7E: push es pusha call LD30 call LD73 jnz LCFE mov cx, [bx+0x8] mov ax, [bx+0x6] call LD19 jnz LCFE out dx, ax mov ax, cx inc dx inc dx out dx, ax mov cx, [bx+0xc] mov ax, [bx+0xa] call LD19 jnz LCFE inc dx inc dx out dx, ax mov ax, cx inc dx inc dx out dx, ax mov ax, [bx+0xe] inc dx inc dx out dx, ax mov ax, 0x1900 mov es, ax test byte [bx], 0xff jz .setupHdPorts mov [es:0x42], bx mov [es:0x44], ds jmp short LCD5 .setupHdPorts: mov [es:0x3e], bx mov [es:0x40], ds call LD3C LCD5: mov ax, [bx+0x10] inc dx inc dx out dx, ax or al, al jmp short LD16 LCDF: push es pusha call LD3C call LD30 add dx, byte +0x8 mov al, 0xa LCEC: mov cx, 0xffff LCEF: push ax in ax, dx or ax, ax pop ax jz LD0D mov ah, [bx] loop LCEF dec al jnz LCEC LCFE: stc pushf call LD30 add dx, byte +0xa in ax, dx and al, 0xfd or al, 0x4 out dx, ax popf LD0D: pushf mov dx, [bx+0x2] in al, dx call LDDF popf LD16: popa pop es ret LD19: push dx mov dx, cx mov cx, ax mov ax, 0x10 mul dx add ax, cx mov cx, dx pop dx jnc .LD2B inc cx .LD2B: test cx, 0xfff0 ret LD30: test byte [bx], 0xff mov dx, 0xffc0 jz .LD3B mov dx, 0xffd0 .LD3B: ret LD3C: push dx push ax mov dx, 0xff30 in ax, dx and ah, 0x7f out dx, ax pop ax pop dx ret LD49: ; {?} hard disk interrupt handler? pusha push ds mov ax, 0x1900 mov ds, ax lds si, [0x3e] mov dx, [si+0x2] in al, dx call L49F pop ds popa iret Int10: ; LD5E pusha push ds mov ax, 0x1900 mov ds, ax lds si, [0x42] mov dx, [si+0x2] in al, dx call L49F pop ds popa iret LD73: push es pusha mov ax, 0x1900 mov es, ax mov cx, 0xffff LD7D: push cx mov cx, 0x4 clc xor ah, ah mov al, [es:0x46] LD88: rcr al, 1 jnc LD8E inc ah LD8E: loop LD88 cmp ah, 0x2 jl LD9D pop cx loop LD7D dec cl jmp short LDDC nop LD9D: pop cx mov cx, 0xffff LDA1: mov al, [bx+0x1] and al, 0xf test [es:0x46], al jz LDB4 loop LDA1 dec cl jmp short LDDC nop LDB4: mov ah, al rol ah, 0x4 test byte [bx], 0xff jnz LDC8 not ah and [es:0x46], ah jmp short LDCA nop LDC8: or al, ah LDCA: or [es:0x46], al mov al, [es:0x46] out 0x2, al ; {TRM appendix C} DMA xor al, al or al, [es:0x47] LDDC: popa pop es ret LDDF: push es push ax pushf mov ax, 0x1900 mov es, ax test byte [bx+0x10], 0xc0 jz .LDFF mov al, [bx+0x1] and al, 0xf not al and al, [es:0x46] mov [es:0x46], al out 0x2, al ; {TRM appendix C} DMA .LDFF: popf pop ax pop es ret push ds pusha mov ax, 0x1900 mov ds, ax mov byte [0x47], 0xff call L48E popa pop ds iret SetUpHDROM: push ds push bx push cx push dx mov ax, 0x0 mov ds, ax cli mov word [0x1d8], IRet ; {?} int 118 mov [0x1da], cs mov word [0x40e], 0x1a00 ; {?} mov word [0x4c], IntFD ; int 19: floppy and hard disk mov [0x4e], cs mov word [0x158], IntFD ; int 86: floppy and hard disk mov [0x15a], cs mov word [0x104], 0x26 ; Hard disk parameter pointer {PR 194} mov [0x106], cs ; {BUG but CS seems wrong; should be 0x1a00} mov ax, 0x1a00 ; Copying 0x48 bytes ROM -> RAM mov ds, ax mov cx, 0x48 nop mov si, HDROMImage nop mov di, 0x0 .copyBytes: mov al, [cs:si] mov [di], al inc si inc di loop .copyBytes sti mov dx, [0x16] ; Get IO port for Cylinder LSB {TRM 189} mov ax, 0x55aa out dx, al mov cx, 0xa ; 10 cycles * 125ns = 1.25us .delay1: loop .delay1 in al, dx ; {?} Verify the IO port retained the cylinder? cmp al, 0xaa jnz .badResponse mov al, ah out dx, al ; mov cx, 0xa ; 10 cycles * 125ns = 1.25us .delay2: loop .delay2 in al, dx cmp al, 0x55 ; {?} Verify the IO port retained the cylinder? jz .goodResponse .badResponse: jmp short badResponseOut nop .goodResponse: mov cx, 0x17 LE8C: push cx mov cx, 0x0 LE90: push cx mov dx, [0xa] ; Get IO port for Software Reset of WD1010 {TRM 188} in al, dx ; Do software reset of WD1010 mov cx, 0xa .delay: loop .delay mov dx, [0x1a] ; Get IO port for SDH register of WD1010 {TRM 189} mov al, 0x20 ; Set HD0, 512 byte sectors out dx, al mov dx, [0x1c] ; {?} IO port 27E of WD1010 seems undefined in al, dx and al, 0xf0 cmp al, 0x50 pop cx jz LEB6 loop LE90 pop cx loop LE8C jmp short badResponseOut nop LEB6: pop cx mov dx, 0x80 ; HD not FD call SetUpHDROMHelper jc setUpHDROMOut ; error? mov dx, 0x80 call SetUpHDROMHelper1 jc setUpHDROMOut ; error? call SetUpHDROMHelper2 jc setUpHDROMOut ; error? call SetUpHDROMHelper1 jc setUpHDROMOut ; error? mov byte [0x3], 0x1 ; {?} set some success flag? jmp short setUpHDROMOut nop SetUpHDROMHelper1: mov ax, 0x1101 ; {?} mov cx, 0x1 int 86 ; Int86FDHD ret SetUpHDROMHelper2: mov cx, 0x501 mov ax, 0xc01 ; {?} int 86 ; Int86FDHD ret badResponseOut: mov ah, 0x7 ; {?} stc ; Set carry to denote error jmp short setUpHDROMOut ; {?} perhaps success route? from where? nop sub ah, ah setUpHDROMOut: pop dx pop cx pop bx pop ds ret SetUpHDROMHelper: mov ax, 0x0 ; reset {?} mov cx, 0x1 ; {?} int 86 ; Int86FDHD ret ; {?} 8 tmp ; indirects for HD IO ports HDROMImage: ; LF01 db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x02, 0x70, 0x02, 0x72 LF10: db 0x02, 0x72, 0x02, 0x74, 0x02, 0x76, 0x02, 0x78, 0x02, 0x7A, 0x02, 0x7C, 0x02, 0x7E, 0x02, 0x7E LF20: db 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x32, 0x01, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 LF30: db 0x02, 0x02, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x32, 0x01, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00 LF40: db 0x00, 0x02, 0x02, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x00 LF49: db 0x15, 0x00, 0xB2, 0x0F, ; {?} LFB2 db 0xFF, 0x0F, 0x75, 0x10, LF51: db 0x1B, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75 LF60: db 0x10, 0x75, 0x10, 0x75, 0x10, 0x4B, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10, 0x60 LF70: db 0x10, 0x75, 0x10, 0x75, 0x10, 0x75, 0x10 IntFD: cmp dl, 0x80 jz .wantFloppy ; Not requesting hard disk? mov ah, 0x1 ; Wanted HD, but not supported! stc ret 0x2 .wantFloppy: push di mov di, 0xf49 sti push ds ; .LF87 push es pusha cmp ah, [cs:di] jnc LFA8 mov bp, sp cld push ax call near [cs:di+0x2] pop ax push ax mov al, ah xor ah, ah add ax, ax add di, ax pop ax call near [cs:di+0x4] jmp short LFAD LFA8: mov al, 0x1 mov [bp+0xf], al LFAD: popa pop es pop ds pop di iret LFB2: ; {?} possibly called via offset from chunk at LF01. disk related. push ax mov ax, 0x1a00 ; Switch DS to 0x1a00 mov ds, ax pop ax mov [0x8], bx ; {?} who calls, and what is bx? mov [0x20], al ; {?} who calls, and what is al? mov al, cl and al, 0xc0 shr al, 0x6 ; {?} get bit 0xc0 mov [0x23], al and cl, 0x3f mov [0x21], cl mov [0x22], ch mov al, [0x24] and al, 0x60 and dl, 0x1 mov [0x2], dl mov cl, 0x3 shl dl, cl or dl, dh or al, dl mov [0x24], al mov byte [0x25], 0x0 mov al, [0x2] call L10f5 mov [0x0], si ; [0x1a000] is sum of ? call L10DC ret mov dx, [0xa] in al, dx mov cx, 0xa .L1007: loop .L1007 mov dx, [0x1c] in al, dx and al, 0xf0 cmp al, 0x50 jz L1018 mov ah, 0x5 stc ret L1018: sub ah, ah ret mov byte [0x25], 0x20 mov ch, 0x0 mov cl, [0x20] L1026: call L1119 mov si, [0x0] mov bl, [si+0x9] call L1133 jc L1040 call L10A1 jc L1048 inc byte [0x21] loop L1026 L1040: mov al, [0x20] sub al, cl mov [bp+0xe], al L1048: jmp short .L107F nop mov byte [0x25], 0x70 call L1119 mov si, [0x0] mov bl, [si+0x9] call L1133 jmp short .L107F nop mov byte [0x25], 0x10 call L1119 mov si, [0x0] mov bl, [si+0xb] call L1133 jmp short .L107F nop mov ah, 0x1 jmp short .L107F nop mov ah, 0x0 jmp short .L107F nop .L107F: mov [0x5], ah mov [bp+0xf], ah or ah, ah jz L1097 call L110A stc lahf mov [bp+0x1a], ah mov ah, [0x5] ret L1097: clc lahf mov [bp+0x1a], ah mov ah, [0x5] ret L10A1: push cx push dx mov cx, 0x0 mov dx, [0x1c] L10AA: in al, dx test al, 0x8 jnz L10B7 loop L10AA mov ah, 0x80 stc jmp short L10D9 nop L10B7: mov cx, 0x200 mov dx, [0xc] mov bx, [0x8] cld L10C3: in al, dx mov [es:bx], al inc bx jnz L10D1 mov ax, es add ax, 0x1000 mov es, ax L10D1: loop L10C3 mov [0x8], bx sub ah, ah L10D9: pop dx pop cx ret ; ds is 0x1a00 L10DC: ; {? perhaps HD reset} push ax push dx mov al, [0x24] mov dx, [0x1a] ; 27C; set SDH register of WD1010; {TRM 189} out dx, al mov si, [0x0] mov ax, [si+0x5] mov dx, [0x10] ; 272; write precomp {TRM 188} out dx, al pop dx pop ax ret ; DS is 0x1a000 L10f5: mov cl, [0x2] mov al, cl mov ch, 0x0 mov si, 0x26 or cl, cl jz .done .L1104: add si, byte +0x11 loop .L1104 .done: ret L110A: push ax push dx mov dx, [0xa] in al, dx mov cx, 0xa .L1114: loop .L1114 pop dx pop ax ret L1119: push ax push cx push dx push si mov cx, 0x6 mov si, 0x20 mov dx, [0x12] cld .L1128: lodsb out dx, al inc dx inc dx loop .L1128 pop si pop dx pop cx pop ax ret L1133: push cx push dx mov dx, [0x1c] sub cx, cx .L113B: in al, dx mov ah, al in al, dx cmp ah, al jnz .L113B and al, 0xf0 cmp al, 0x50 jz .L1154 loop .L113B dec bl jnz .L113B mov ah, 0x80 jmp short .L1164 nop .L1154: mov al, ah test al, 0x1 jz .L1167 mov dx, [0xe] in al, dx and al, 0xd6 call L116C .L1164: stc jmp short .L1169 .L1167: sub ah, ah .L1169: pop dx pop cx ret L116C: test al, 0x1 jz .L1173 mov ah, 0x2 ret .L1173: test al, 0x2 jz .L117A mov ah, 0x40 ret .L117A: test al, 0x4 jz .L1181 mov ah, 0x1 ret .L1181: test al, 0x10 jz .L1188 mov ah, 0x4 ret .L1188: test al, 0x40 jz .L118F mov ah, 0x10 ret .L118F: test al, 0x80 jz .L1196 mov ah, 0xb ret .L1196: mov ah, 0xbb ret IRet: iret ;; padding L119a: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L11a0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L11b0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L11c0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L11d0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L11e0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L11f0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1200: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1210: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1220: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1230: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1240: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1250: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1260: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1270: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1280: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1290: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L12a0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L12b0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L12c0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L12d0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L12e0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L12f0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; Character set CharSet8x8: L1300: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0xa5, 0x81, 0xa5, 0x99, 0x42, 0x3c L1310: db 0xc3, 0xbd, 0x5a, 0x7e, 0x5a, 0x66, 0xbd, 0xc3, 0x22, 0x77, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00 L1320: db 0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x1c, 0x08, 0x49, 0x7f, 0x49, 0x08, 0x3e, 0x00 L1330: db 0x08, 0x1c, 0x3e, 0x7f, 0x2a, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 L1340: db 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00 L1350: db 0xff, 0xc3, 0xbd, 0xbd, 0xbd, 0xc3, 0xff, 0xff, 0x0f, 0x03, 0x05, 0x38, 0x44, 0x44, 0x38, 0x00 L1360: db 0x1c, 0x22, 0x22, 0x1c, 0x08, 0x3e, 0x08, 0x00, 0x1f, 0x11, 0x11, 0x1f, 0x10, 0x30, 0x70, 0x00 L1370: db 0x3f, 0x21, 0x21, 0x3f, 0x21, 0x22, 0x40, 0x00, 0x49, 0x2a, 0x36, 0x63, 0x36, 0x2a, 0x49, 0x00 L1380: db 0x40, 0x70, 0x7c, 0x7f, 0x7c, 0x70, 0x40, 0x00, 0x01, 0x07, 0x1f, 0x7f, 0x1f, 0x07, 0x01, 0x00 L1390: db 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x24, 0x00 L13a0: db 0x3f, 0x49, 0x49, 0x49, 0x39, 0x09, 0x09, 0x00, 0x18, 0x20, 0x1c, 0x22, 0x1c, 0x02, 0x0c, 0x00 L13b0: db 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x08, 0x1c, 0x2a, 0x08, 0x2a, 0x1c, 0x08, 0xff L13c0: db 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08 L13d0: db 0x00, 0x04, 0x02, 0xff, 0x02, 0x04, 0x00, 0x00, 0x00, 0x20, 0x40, 0xff, 0x40, 0x20, 0x00, 0x00 L13e0: db 0x00, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00 L13f0: db 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00 L1400: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00 L1410: db 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00 L1420: db 0x08, 0x1e, 0x28, 0x1c, 0x0a, 0x3c, 0x08, 0x00, 0x00, 0x62, 0x64, 0x08, 0x10, 0x26, 0x46, 0x00 L1430: db 0x30, 0x48, 0x48, 0x30, 0x4a, 0x44, 0x3a, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 L1440: db 0x04, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00 L1450: db 0x00, 0x22, 0x14, 0x3e, 0x14, 0x22, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00 L1460: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 L1470: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00 L1480: db 0x3e, 0x43, 0x45, 0x49, 0x51, 0x61, 0x3e, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3e, 0x00 L1490: db 0x3e, 0x41, 0x06, 0x18, 0x20, 0x40, 0x7f, 0x00, 0x3e, 0x41, 0x01, 0x1e, 0x01, 0x41, 0x3e, 0x00 L14a0: db 0x06, 0x0a, 0x12, 0x22, 0x7f, 0x02, 0x02, 0x00, 0x7e, 0x40, 0x7c, 0x02, 0x01, 0x42, 0x3c, 0x00 L14b0: db 0x18, 0x20, 0x40, 0x7e, 0x41, 0x41, 0x3e, 0x00, 0x7f, 0x41, 0x02, 0x04, 0x08, 0x08, 0x08, 0x00 L14c0: db 0x3e, 0x41, 0x41, 0x3e, 0x41, 0x41, 0x3e, 0x00, 0x3e, 0x41, 0x41, 0x3f, 0x01, 0x02, 0x0c, 0x00 L14d0: db 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10 L14e0: db 0x00, 0x04, 0x08, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00 L14f0: db 0x00, 0x10, 0x08, 0x04, 0x08, 0x10, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x0c, 0x10, 0x00, 0x10, 0x00 L1500: db 0x1e, 0x21, 0x4d, 0x55, 0x4e, 0x20, 0x1e, 0x00, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x41, 0x41, 0x00 L1510: db 0x7e, 0x21, 0x21, 0x3e, 0x21, 0x21, 0x7e, 0x00, 0x1e, 0x21, 0x40, 0x40, 0x40, 0x21, 0x1e, 0x00 L1520: db 0x7c, 0x22, 0x21, 0x21, 0x21, 0x22, 0x7c, 0x00, 0x7f, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x7f, 0x00 L1530: db 0x7f, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x00, 0x1e, 0x21, 0x40, 0x4f, 0x41, 0x21, 0x1e, 0x00 L1540: db 0x41, 0x41, 0x41, 0x7f, 0x41, 0x41, 0x41, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00 L1550: db 0x0e, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18, 0x00, 0x41, 0x42, 0x44, 0x78, 0x44, 0x42, 0x41, 0x00 L1560: db 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7f, 0x00, 0x41, 0x63, 0x55, 0x49, 0x41, 0x41, 0x41, 0x00 L1570: db 0x41, 0x61, 0x51, 0x49, 0x45, 0x43, 0x41, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x41, 0x41, 0x3e, 0x00 L1580: db 0x7e, 0x41, 0x41, 0x7e, 0x40, 0x40, 0x40, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x45, 0x42, 0x3d, 0x00 L1590: db 0x7e, 0x41, 0x41, 0x7e, 0x44, 0x42, 0x41, 0x00, 0x3e, 0x41, 0x40, 0x3e, 0x01, 0x41, 0x3e, 0x00 L15a0: db 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x3e, 0x00 L15b0: db 0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x41, 0x41, 0x49, 0x49, 0x55, 0x63, 0x22, 0x00 L15c0: db 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x00 L15d0: db 0x7f, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7f, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00 L15e0: db 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00 L15f0: db 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff L1600: db 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x3e, 0x42, 0x3d, 0x00 L1610: db 0x40, 0x40, 0x5c, 0x62, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x42, 0x3c, 0x00 L1620: db 0x02, 0x02, 0x3a, 0x46, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x40, 0x3c, 0x00 L1630: db 0x04, 0x0a, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x46, 0x3a, 0x02, 0x3c L1640: db 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1c, 0x00 L1650: db 0x04, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x24, 0x18, 0x20, 0x20, 0x22, 0x24, 0x28, 0x34, 0x22, 0x00 L1660: db 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x76, 0x49, 0x49, 0x49, 0x49, 0x00 L1670: db 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00 L1680: db 0x00, 0x00, 0x5c, 0x62, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00, 0x3a, 0x46, 0x46, 0x3a, 0x02, 0x02 L1690: db 0x00, 0x00, 0x5c, 0x62, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x3c, 0x02, 0x7c, 0x00 L16a0: db 0x10, 0x10, 0x7c, 0x10, 0x10, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00 L16b0: db 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x41, 0x49, 0x55, 0x63, 0x22, 0x00 L16c0: db 0x00, 0x00, 0x42, 0x24, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x3c L16d0: db 0x00, 0x00, 0x3e, 0x04, 0x08, 0x10, 0x3e, 0x00, 0x0c, 0x10, 0x10, 0x20, 0x10, 0x10, 0x0c, 0x00 L16e0: db 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x30, 0x08, 0x08, 0x04, 0x08, 0x08, 0x30, 0x00 L16f0: db 0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x00 ; Character set CharSet8x16: L1700: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0: null L1710: db 0x00, 0x3c, 0x42, 0x81, 0xa5, 0x81, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 1: smiley L1720: db 0x00, 0xc3, 0xbd, 0x7e, 0x5a, 0x7e, 0x5a, 0x66, 0xbd, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 2: inverse smiley L1730: db 0x00, 0x00, 0x22, 0x77, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1740: db 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1750: db 0x00, 0x00, 0x1c, 0x08, 0x49, 0x7f, 0x49, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1760: db 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x2a, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1770: db 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1780: db 0x00, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1790: db 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L17a0: db 0x00, 0xff, 0xff, 0xc3, 0xbd, 0xbd, 0xbd, 0xc3, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L17b0: db 0x00, 0x0f, 0x03, 0x05, 0x39, 0x44, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L17c0: db 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x22, 0x1c, 0x08, 0x3e, 0x08, 0x00, 0x00, 0x00 L17d0: db 0x00, 0x00, 0x1f, 0x11, 0x11, 0x1f, 0x10, 0x10, 0x10, 0x30, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 L17e0: db 0x00, 0x00, 0x3f, 0x21, 0x21, 0x3f, 0x21, 0x21, 0x21, 0x22, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00 L17f0: db 0x00, 0x00, 0x49, 0x2a, 0x36, 0x63, 0x36, 0x2a, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1800: db 0x00, 0x00, 0x40, 0x70, 0x7c, 0x7f, 0x7c, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1810: db 0x00, 0x00, 0x01, 0x07, 0x1f, 0x7f, 0x1f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1820: db 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08 L1830: db 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1840: db 0x00, 0x00, 0x3f, 0x49, 0x49, 0x49, 0x49, 0x39, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1850: db 0x00, 0x00, 0x1e, 0x21, 0x1c, 0x22, 0x22, 0x1c, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1860: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1870: db 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0xff L1880: db 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 L1890: db 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08 L18a0: db 0x00, 0x00, 0x00, 0x04, 0x02, 0xff, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L18b0: db 0x00, 0x00, 0x00, 0x20, 0x40, 0xff, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L18c0: db 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L18d0: db 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L18e0: db 0x00, 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L18f0: db 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1900: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1910: db 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1920: db 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1930: db 0x00, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1940: db 0x00, 0x08, 0x3f, 0x48, 0x48, 0x3e, 0x09, 0x09, 0x7e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1950: db 0x00, 0x20, 0x51, 0x22, 0x04, 0x08, 0x10, 0x22, 0x45, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1960: db 0x00, 0x10, 0x28, 0x28, 0x10, 0x28, 0x44, 0x45, 0x42, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1970: db 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1980: db 0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1990: db 0x00, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L19a0: db 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L19b0: db 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L19c0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 L19d0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L19e0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L19f0: db 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a00: db 0x00, 0x3e, 0x41, 0x43, 0x45, 0x49, 0x51, 0x61, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a10: db 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a20: db 0x00, 0x3e, 0x41, 0x01, 0x02, 0x0c, 0x30, 0x40, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a30: db 0x00, 0x3e, 0x41, 0x01, 0x01, 0x1e, 0x01, 0x01, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a40: db 0x00, 0x02, 0x06, 0x0a, 0x12, 0x22, 0x7f, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a50: db 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x01, 0x01, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a60: db 0x00, 0x0c, 0x10, 0x20, 0x40, 0x7c, 0x42, 0x41, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a70: db 0x00, 0x7f, 0x41, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a80: db 0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1a90: db 0x00, 0x3e, 0x41, 0x41, 0x41, 0x3f, 0x01, 0x02, 0x04, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1aa0: db 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ab0: db 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 L1ac0: db 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ad0: db 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ae0: db 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1af0: db 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b00: db 0x00, 0x1e, 0x21, 0x4d, 0x55, 0x51, 0x4e, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b10: db 0x00, 0x08, 0x14, 0x22, 0x41, 0x41, 0x7f, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b20: db 0x00, 0x7e, 0x41, 0x41, 0x41, 0x7e, 0x41, 0x41, 0x41, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b30: db 0x00, 0x3e, 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b40: db 0x00, 0x7c, 0x42, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b50: db 0x00, 0x7f, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b60: db 0x00, 0x7f, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b70: db 0x00, 0x1e, 0x21, 0x40, 0x40, 0x4f, 0x41, 0x41, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b80: db 0x00, 0x41, 0x41, 0x41, 0x41, 0x7f, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1b90: db 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ba0: db 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1bb0: db 0x00, 0x41, 0x42, 0x44, 0x48, 0x50, 0x68, 0x44, 0x42, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1bc0: db 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1bd0: db 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1be0: db 0x00, 0x41, 0x41, 0x61, 0x51, 0x49, 0x45, 0x43, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1bf0: db 0x00, 0x3e, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c00: db 0x00, 0x7e, 0x41, 0x41, 0x41, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c10: db 0x00, 0x3e, 0x41, 0x41, 0x41, 0x41, 0x49, 0x45, 0x42, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c20: db 0x00, 0x7e, 0x41, 0x41, 0x41, 0x7e, 0x48, 0x44, 0x42, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c30: db 0x00, 0x3e, 0x41, 0x40, 0x40, 0x3e, 0x01, 0x01, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c40: db 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c50: db 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c60: db 0x00, 0x41, 0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c70: db 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c80: db 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1c90: db 0x00, 0x41, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ca0: db 0x00, 0x7f, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1cb0: db 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1cc0: db 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1cd0: db 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ce0: db 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1cf0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 L1d00: db 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d10: db 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x3e, 0x42, 0x42, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d20: db 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d30: db 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d40: db 0x00, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d50: db 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d60: db 0x00, 0x0c, 0x12, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d70: db 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x02, 0x1c, 0x00, 0x00 L1d80: db 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1d90: db 0x00, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1da0: db 0x00, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00 L1db0: db 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x68, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1dc0: db 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1dd0: db 0x00, 0x00, 0x00, 0x00, 0x76, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1de0: db 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1df0: db 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e00: db 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00 L1e10: db 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00 L1e20: db 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e30: db 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x30, 0x0c, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e40: db 0x00, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e50: db 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e60: db 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e70: db 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x49, 0x55, 0x63, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e80: db 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1e90: db 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x02, 0x1c, 0x00, 0x00 L1ea0: db 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1eb0: db 0x00, 0x0c, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ec0: db 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ed0: db 0x00, 0x30, 0x08, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ee0: db 0x00, 0x30, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1ef0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ;; Power on: CS=0xff0, IP=0 PowerOn: ; L1f00 mov ax, 0xff mov dx, 0xfffe ; {? port 0xfffe} out dx, ax mov bx, ax ; bx = 0xff not ax ; ax = 0 mov dx, 0xfffe in ax, dx xor ax, bx and ax, 0xdfff ; {? what is reading from port 0xfffe telling us?) jz .continue .hang: jmp short .hang .continue: ; L1f18 mov ax, 0xc0be mov dx, 0xffa8 out dx, ax ; {? port 0xffa8} mov ax, 0x1f8 mov dx, 0xffa6 out dx, ax mov ax, 0x3e mov dx, 0xffa4 out dx, ax mov al, 0x0 mov dx, 0x0 out dx, al ; {TRM appendix C, turn off devices} mov al, 0xc0 mov dx, 0x101 out dx, al ; {TRM appendix C, video: 800x400, bus not 9007} mov dx, 0x56 mov al, 0xaa out dx, al ; {? port 0x56} nop nop mov dx, 0x54 mov al, 0x5 out dx, al ; {TRM appendix C, 8255 direction, read keyboard} mov al, 0x3 mov dx, 0x52 %ifdef DEBUG in al, dx ; {?} Guessing something like this may have been in original ; source. Allows selection of different hardware setup. %else nop ; Release builds always leave al=3 %endif mov bp, 0x1f6a nop .checkProfile: cmp al, [cs:bp+0x0] je .foundProfile add bp, byte +0x10 jmp short .checkProfile .foundProfile: ;L1f5c: mov ax, [cs:bp+0x2] mov dx, 0xffa0 out dx, ax jmp word 0xfe00:0x0 ; Jump to StartOfBoot nop ; Hardware Profiles (or so I call them) ; cs:bp is set (in PowerOn) to point to one of these 4 16-byte blocks. Describes hardware. ; Maybe for debug vs production, or hardware revisions? ; 0 index (influences font setup) ; 1 max allowed 64k banks of RAM ; 2 is written to IO port 0xffa0 {? why?} ; 3 ; 4 Address Control Register {TRM appendix C} when 128k installed ; 5 Device power-on, reset, DMA 8237, etc L1f6a: db 0x00, 0x08, 0x3f, 0xe0, 0x44, 0x00, 0x48, 0x00, 0x50, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00 L1f7a: db 0x01, 0x08, 0x3b, 0xe0, 0xc4, 0x00, 0xc8, 0x00, 0xd0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00 L1f8a: db 0x02, 0x0c, 0x3f, 0xf8, 0xc3, 0x00, 0xc7, 0x00, 0xcb, 0x00, 0xcf, 0x00, 0xd3, 0x00, 0xd7, 0x00 L1f9a: db 0x03, 0x0c, 0x3f, 0xf8, 0xc3, 0x10, 0xc7, 0x10, 0xcb, 0x10, 0xcf, 0x10, 0xd3, 0x10, 0xd7, 0x10 L1faa: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1fb0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1fc0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1fd0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 L1fe0: db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x3a L1ff0: db 0xea, 0x00, 0x1f, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00