mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-08 19:32:39 +08:00
55 KiB
55 KiB
Entry point (MS-DOS 5.00) 1.44MB disk image (on my hard drive, boot144.dsk). Configuration menu option "nothing". 0ADC segment may change location based on configuration.
--
0060:0020 WORD MS-DOS product number [see INT DCh CL=12h]
0060:0022 WORD Internal revision number [see INT DCh CL=15h AH=0]
0060:002E WORD INT DCh / ANSI segment (in this dump, 0ADCh)
0060:0030 WORD ?? (in this dump, 3800h)
0060:0032 WORD Text VRAM segment (A000h)
0060:0037 BYTE ??
0060:0068 WORD RS-232C channel 0 AUX protocol [undocumented PC-98 webtech] [see INT DCh CL=0Ah, INT DCh CL=0Eh AH=01h]
0060:008A BYTE kanji / graph mode flag
0060:008B BYTE ??
0060:00A5 BYTE ??
0060:00A6 BYTE ??
0060:00B4 BYTE INT DCh in-progress flag [undocumented PC-98 webtech]
0060:0110 BYTE Cursor Y coordinate
0060:0111 BYTE Function row display (0=off 1=on 2=shift function keys)
0060:0112 BYTE Scroll range lower limit
0060:0113 BYTE Number of screen lines
0060:0114 BYTE Erasure attribute (usually E1h)
0060:0115 BYTE kanji upper byte storage flag
0060:0116 BYTE kanji upper byte
0060:0117 BYTE Line wrap flag
0060:0118 BYTE Scroll speed (0=normal 1=slow)
0060:0119 WORD Erasure character (usually 20h)
0060:011B BYTE Cursor display state (0=off 1=on)
0060:011C BYTE Cursor X coordinate
0060:011D BYTE Character attribute (i.e. controlled by <ESC>[m ) [INT DCh CL=10h AH=02h]
0060:011E BYTE Scroll range upper limit
0060:011F BYTE Scroll "weight" (delay, apparently?) (0001h = normal E000h = slow)
0060:0124 WORD ACFh BX value (?))
0060:0128 BYTE ANSI escape handling state (0=normal 1=ESC 2>=ANSI processing)
0060:0129 BYTE ANSI escape handling state (?)
0060:012A BYTE ANSI escape handling state (?) 0 = ? 1 = ESC[> 2 = ESC[? 3 = ESC[=
0060:012B BYTE Saved cursor attribute ( ESC [s )
0060:0134 WORD ANSI escape handling pointer of some kind (?)
0060:0136 BYTE drive number last accessed by IO.SYS block driver [INT DCh CL=13h]
0060:013C WORD display attribute in extended attribute mode [INT DCh CL=10h AL=02h]
0060:013E WORD erasure attribute in extended attribute mode [INT DCh CL=10h AL=02h]
0060:014E BYTE some sort of flag
0060:0162 WORD ??
0060:0214 WORD:WORD 16-bit far pointer (0ADC:3126)
0060:0268 WORD ??
0060:05DB WORD stored AX value from caller
0060:05DD WORD stored SS value from caller
0060:05DF WORD stored SP value from caller (after INT DCh int frame and PUSH DS)
0060:05E1 WORD stored DS value from caller
0060:05E3 WORD stored DX value from caller
0060:05E5 WORD stored BX value from caller
0060:0767 Stack pointer (from DOS segment), stack switches to on entry to procedure
0060:17FA WORD ??
0060:1802 WORD ??
0060:197A BYTE ??
0060:1DC4 BYTE ??
0060:2852 BYTE x 0x28 ANSI escape parsing state (such as, numeric values from ESC[m )
0060:2A7A WORD ??
0060:2A7C WORD ??
0060:2C86 WORD x 0x1A ??
0060:36B3 INT DCh entry point
0060:3B30 Subroutine called on INT DCh if 0060:014E is nonzero
--
INT DC = 60:36B3
0060:36B3:
if BYTE PTR cs:[014E] == 0 jmp 0060:36BE
CALL 3B30h
0060:36BE:
jmp far WORD PTR cs:[0214] (0ADC:3126)
--
0060:3B30: (called by INT DCh entry point if BYTE PTR CS:[014E] != 0
PUSH DS, ES, CX, SI, DI
DS:SI = WORD PTR cs:[3B28] (FFFF:0090)
ES:DI = WORD PTR cs:[3B2C] (0000:0080)
ZF = ((result=_fmemcmp(DS:SI,ES:DI,16)) == 0) (CX = 8, REP CMPSW) ; <- Testing A20 gate, apparently?
POP DI, SI, CX, ES, DS
IF result == 0 JMP 3B4Ch (if ZF=1)
return
0060:3B4C: (if _fmemcmp(DS:SI,ES:DI,16) == 0)
PUSH AX, BX
AH = 5
CALL FAR WORD PTR cs:[014F] ; <- ??? Pointer so far has been either 0000:0000 or FFFF:FFFF
POP BX, AX
return
; ^ NOTE: Not sure, but this may be a call into HIMEM.SYS (XMS), in which case AH = 5 means Local Enable A20
--
0ADC:0030 WORD DOS kernel segment (60h)
--
0ADC:0032:
PUSH DS
DS = WORD PTR CS:[0030] ; DOS kernel segment (60h)
IF (BYTE PTR DS:[197A] & 3) == 0 JMP 61h ; 0060:197A
0ADC:003F:
ES = 0
CX = WORD PTR ES:[05EA] ; 0000:05EA Disk 0 Parameter table segment??
IF CX != WORD PTR DS:[002E] JMP 52h ; ??
DI = 5EAh
WORD PTR ES:[DI] = AX, DI += 2 ; STOSW
0ADC:0052:
CX = WORD PTR ES:[05EE] ; 0000:05EE Disk 1 Parameter table segment?
IF CX != WORD PTR DS:[002E] JMP 61h
DI = 5EEh
WORD PTR ES:[DI] = AX, DI += 2 ; STOSW
0ADC:0061:
POP DS
ES = WORD PTR CS:[0030] ; DOS kernel segment (60h)
WORD PTR ES:[002E] = AX ; ??
DI = 162h
CX = 36h
0ADC:0071:
WORD PTR ES:[DI] = AX, DI += 4 ; STOSW ; INC DI ; INC DI
IF CX > 0 THEN CX--, JMP 71h ; LOOP 71h
0ADC:0076:
return far ; RETF
--
0ADC:0A00 Subroutine lookup table
Referred from 0ADC:0AAC, CL is single char or first byte of kanji
CL=10h AH=00h, search by CL register from caller, or normal CON output.
. . . . . .
0ADC:00000A00 07 E7 10 08 19 11 09 F8 10 0A 49 11 0B 3A 11 0C ..........I..:..
. . . . .
0ADC:00000A10 8C 11 0D 5E 11 1A 7D 11 1B C1 10 1E 6B 11 00 B3 ...^..}.....k...
|END
0ADC:00000A20 11 5B B2 0B 3D E4 0A 2A 84 0B 28 77 0B 44 90 0B .[..=..*..(w.D..
CL value | Subroutine address
CL = 0x07 0x10E7 ; CTRL+G / BEL
CL = 0x08 0x1119 ; CTRL+H / BACKSPACE / LEFT ARROW
CL = 0x09 0x10F8 ; CTRL+I / TAB
CL = 0x0A 0x1149 ; CTRL+J / DOWN ARROW
CL = 0x0B 0x113A ; CTRL+K / UP ARROW
CL = 0x0C 0x118C ; CTRL+L / RIGHT ARROW
CL = 0x0D 0x115E ; CTRL+M / CARRIAGE RETURN
CL = 0x1A 0x117D ; CTRL+Z / SUBSTITUE
CL = 0x1B 0x10C1 ; ESCAPE
CL = 0x1E 0x116B ; RECORD SEPARATOR
Any other (0) 0x11B3
The ESCAPE subroutine sets BYTE PTR [60:128] = 1, BYTE PTR [60:129] = 1,
and WORD PTR [60:134] = 0x2852
--
0ADC:0A21 Subroutine lookup table
Referred from 0ADC:0AC0, CL is byte from caller when (BYTE PTR DS:[0128] == 2)
In most cases this is called with CL the first byte after ANSI ESCAPE code.
. . . . .
0ADC:00000A20 11 5B B2 0B 3D E4 0A 2A 84 0B 28 77 0B 44 90 0B .[..=..*..(w.D..
. . . . |END
0ADC:00000A30 45 8D 0B 4D 99 0B 29 26 0B 00 93 0B 41 49 0C 42 E..M..)&....AI.B
CL value | Subroutine address
CL = 0x5B 0x0BB2 ; ESC [
CL = 0x3D 0x0AE4 ; ESC =
CL = 0x2A 0x0B84 ; ESC *
CL = 0x28 0x0B77 ; ESC (
CL = 0x44 0x0B90 ; ESC D
CL = 0x45 0x0B8D ; ESC E
CL = 0x4D 0x0B99 ; ESC M
CL = 0x29 0x0B26 ; ESC )
Any other (0) 0x0B93 ; ESC (anything else)
The subroutine for (anything else) sets BYTE PTR [60:128] = 0, cancelling the
ESC handling and ignoring the byte.
--
0ADC:0A3C Subroutine lookup table
Referred from ADC:0BDC, CL is the last byte of the ANSI ESC [ code.
This is called only on the final byte, not the intermediate digits and
semicolons of the code.
. . . . . .
0ADC:00000A3C 41 49 0C 42 6C 0C 43 93 0C 44 BA 0C 48 DD 0C 4A AI.Bl.C..D..H..J
. . . . .
0ADC:00000A4C 25 0D 4B 69 0D 4C 3E 0E 4D 69 0E 6D BD 0D 66 DD %.Ki.L>.Mi.m..f.
. . . . .
0ADC:00000A5C 0C 68 32 0F 6C 9A 0E 6E CB 0F 73 24 10 70 6F 10 .h2.l..n..s$.po.
. . . . . |END
0ADC:00000A6C 75 48 10 3E 88 0E 3F 8E 0E 3D 94 0E 00 C0 10 90 uH.>..?..=......
CL value | Subroutine address
CL = 0x41 0x0C49 ; ESC [ A
CL = 0x42 0x0C6C ; ESC [ B
CL = 0x43 0x0C93 ; ESC [ C
CL = 0x44 0x0CBA ; ESC [ D
CL = 0x48 0x0CDD ; ESC [ H
CL = 0x4A 0x0D25 ; ESC [ J
CL = 0x4B 0x0D69 ; ESC [ K
CL = 0x4C 0x0E3E ; ESC [ L
CL = 0x4D 0x0E69 ; ESC [ M
CL = 0x6D 0x0DBD ; ESC [ m
CL = 0x66 0x0CDD ; ESC [ f
CL = 0x68 0x0F32 ; ESC [ h
CL = 0x6C 0x0E9A ; ESC [ l
CL = 0x6E 0x0FCB ; ESC [ n
CL = 0x73 0x1024 ; ESC [ s
CL = 0x70 0x106F ; ESC [ p
CL = 0x75 0x1048 ; ESC [ u
CL = 0x3E 0x0E88 ; ESC [ >
CL = 0x3F 0x0E8E ; ESC [ ?
CL = 0x3D 0x0E94 ; ESC [ =
Any other (0) 0x10C0 ; ESC [ (anything else)
The anything else handler returns immediately (escape code is ignored) and
the calling code resets the flag and allows the console to proceed normally.
--
. . . . . . . .
0ADC:00000A7C E2 12 F2 12 E2 12 CA 12 BC 12 F2 12 C3 12 D1 12 ................
. . |END
0ADC:00000A8C C3 12 D8 12 E8 01 00 CB B8 00 01 C3 E8 01 00 CB ................
0ADC:0A7C table (routine 0ADC:1201 return from CALL 129Dh)
AX = 0x0000 DL = 0x00 0x12E2
AX = 0x0000 DL = 0x01 0x12F2
AX = 0x0001 DL = 0x00 0x12E2
AX = 0x0001 DL = 0x01 0x12CA
AX = 0x0002 DL = 0x00 0x12BC
AX = 0x0002 DL = 0x01 0x12F2
AX = 0x0003 DL = 0x00 0x12C3
AX = 0x0003 DL = 0x01 0x12D1
AX = 0x0004 DL = 0x00 0x12C3
AX = 0x0004 DL = 0x01 0x12D8
--
0ADC:0A90:
CALL A94h
return far ; RETF
0ADC:0A94:
MOV AX,0100h
return
--
0ADC:0A98:
CALL A9Ch
return far ; RET
--
0ADC:0A9C: (CL=10h AH=00h, at this time CL == caller's DL and DS = DOS segment 60h)
IF BYTE PTR DS:[0128] != 0 JMP AB5 (60:128)
IF CL < 0x20 JMP AACh
CALL 11B3h
0ADC:0AAC: (CL < 0x20)
BX = 0A00h
CALL 0ACFh
CALL NEAR BX (BX comes from subroutine ACFh)
return
0ADC:0AB5: (BYTE PTR DS:[0128] != 0) aka (60:128)
(BYTE DS:[0128])++
IF BYTE PTR DS:[0128] != 2 JMP 0ACAh
0ADC:0AC0: (BYTE PTR DS:[0128] == 2)
BX = 0A21h
CALL 0ACFh
WORD PTR DS:[0124] = BX (BX comes from subroutine ACFh) (60:124)
0ADC:0ACA: (jmp here from BYTE PTR DS:[0128] != 2 compare under 0ADC:0AB5)
CALL NEAR WORD PTR DS:[0124]
return
--
; Entry: BX = memory location of a lookup table, 3 bytes/entry in this format:
; BYTE subroutine number
; WORD subroutine address
; CL = subroutine number to match
;
; Exit: BX = subroutine address
0ADC:0ACF:
IF BYTE PTR CS:[BX] == 0 JMP ADFh
IF BYTE PTR CS:[BX] == CL JMP ADFh
BX += 3
JMP ACFh
0ADC:0ADF:
BX = WORD PTR CS:[BX+1]
return
--
; Entry: CL = character code
;
; This is executed per character after ESC =
0ADC:0AE4:
BX = WORD PTR DS:[0134] ; [0134] is often set to 2852h
WORD PTR DS:[BX],CL
WORD PTR DS:[0134] += 1
IF BYTE PTR DS:[0128] < 0x04 JMP B18h
0ADC:0AF5:
BX = 2853h ; ANSI escape parsing address + 1
0ADC:0AF8:
CX = WORD PTR DS:[BX]
0ADC:0AFA:
AL = CL
AH = BYTE PTR DS:[0112] ; Scroll range lower limit
CALL B19h
BYTE PTR DS:[0110],AL ; Cursor Y position
AL = CH
AH = 0x4F
CALL B19h
BYTE PTR DS:[011C],AL ; Cursor X position
CALL 1535h ; update cursor position
BYTE PTR DS:[0128] = 0
0ADC:0B18:
return
--
0ADC:0B19:
AL = ((AL >= 0x20) ? (AL - 0x20)) : 0 ; SUB AL, 20h ; JNC B1Fh ; MOV AL,00h
0ADC:0B1F:
AL = ((AL > AH) ? AH : AL) ; CMP AL, AH ; JBE B25h ; MOV AL, AH
0ADC:0B25:
return
--
; Entry: CL = character code
;
; This is executed per character after ESC ) until the end of the ANSI code
0ADC:0B26:
IF BYTE PTR DS:[0128] != 3 JMP B76h
IF CL == 0x33 JMP B43h
IF CL != 0x30 JMP B4Dh
0ADC:0B37:
BYTE PTR DS:[008A] = 0x01
BYTE PTR DS:[008B] = 0x20
JMP B4Dh
0ADC:0B43:
BYTE PTR DS:[008B] = 0x67
BYTE PTR DS:[008A] = 0x00
0ADC:0B4D:
IF BYTE PTR DS:[0111] == 0 JMP B71h
0ADC:0B54:
PUSH ES
ES = WORD PTR DS:[0032] ; video ram segment
DH = (BYTE PTR DS:[0112]) + 1
DL = 0
CALL 14F5h ; convert row DH col DL to video memory address
BX += 2
AX = BYTE PTR DS:[008B]
WORD PTR DS:[BX] = AX
POP ES
0ADC:0B71:
BYTE PTR DS:[0128] = 0
0ADC:0B76:
return
--
; Entry: CL = character code
;
; This is executed per character after ESC ( until the end of the ANSI code
0ADC:0B77:
IF BYTE PTR DS:[0128] < 3 JMP B83h
BYTE PTR DS:[0128] = 0
0ADC:0B83:
return
--
; Entry: CL = character code
;
; This is executed per character after ESC * until the end of the ANSI code
0ADC:0B84:
CALL 117Dh ; CTRL+Z handling
BYTE PTR DS:[0128] = 0
0ADC:0B8C:
return
--
; Entry: CL = character code
;
; This is executed per character after ESC E until the end of the ANSI code
0ADC:0B8D:
CALL 115Eh ; carriage return
0ADC:0B90:
CALL 1149h ; line feed / down arrow
0ADC:0B93: ; <- table jumps here for unknown escapes
BYTE PTR DS:[0128] = 0
0ADC:0B98:
return
--
; Entry: CL = character code
;
; This is executed per character after ESC M
0ADC:0B99:
IF BYTE PTR DS:[0110] == 0 JMP BA9h ; Move cursor up one row
BYTE PTR DS:[0110] -= 1
CALL 1535h ; update cursor position
JMP BACh
0ADC:0BA9:
CALL 13B0h ; scroll region down one line
0ADC:0BAC:
BYTE PTR DS:[0128] = 0
0ADC:0BB1:
return
--
; Entry: CL = character code
;
; This is executed per character after ESC [ until the end of the ANSI code
0ADC:0BB2:
IF BYTE PTR DS:[0128] == 0x02 JMP BF3h
IF CL == 0x3B JMP C05h
IF CL == 0x27 JMP C1Bh
IF CL == 0x22 JMP C1Bh
IF BYTE PTR DS:[012A] == 0xFF JMP C2Ch
IF CL >= 0x3A JMP BDCh
CL = CL AND 0x0F
IF CL <= 0x09 JMP BF4h
0ADC:0BDC:
BX = 0A3Ch
CALL ACFh
SI = 2852h
CALL NEAR BX
0ADC:0BE7:
IF BYTE PTR DS:[012A] != 0 JMP BF3h
BYTE PTR DS:[0128] = 0
0ADC:0BF3:
return
--
; ESC [ A
; SI = ANSI escape area (2852h)
0ADC:0C49:
IF BYTE PTR DS:[0129] != 1 JMP C6Bh
0ADC:0C50:
CX = WORD PTR DS:[SI] ; numeric value before "A" character, parameter
0ADC:0C52:
AX = BYTE PTR DS:[0110] ; Cursor Y position
IF CX == 0 THEN CX = 1 ; AND CX, CX ; JNE C5Eh ; MOV CX, 1
0ADC:0C5E:
IF CX > AX THEN CX = AX ; CMP AX, CX ; JNC C64h ; MOV CX, AX
0ADC:0C64:
BYTE PTR DS:[0110] -= CL ; Cursor Y position -= parameter
CALL 1535h ; update cursor position on screen
0ADC:0C6B:
return
--
; ESC [ B
; SI = ANSI escape area (2852h)
0ADC:0C6C:
IF BYTE PTR DS:[0129] != 1 JMP C92h
CX = WORD PTR DS:[SI]
0ADC:0C75:
AL = (BYTE PTR DS:[0112]) - (BYTE PTR DS:[0110]), AH = 0
IF CX == 0 THEN CX = 1 ; AND CX, CX ; JNE C85h ; MOV CX, 1
IF CX > AX THEN CX = AX ; CMP AX, CX ; JNC C8Bh ; MOV CX, AX
BYTE PTR DS:[0110] += CL ; Cursor Y position += CL
CALL 1535h ; update cursor position on screen
0ADC:0C92:
return
--
; ESC [ C
; SI = ANSI escape area (2852h)
0ADC:0C93:
IF BYTE PTR DS:[0129] != 1 JMP CB9h
CX = WORD PTR DS:[SI]
0ADC:0C9C:
AX = 0x4F
if (AL -= BYTE PTR DS:[011C]) < 0 JMP CB6h ; SUB AL,[011C] ; JC CB6h
IF CX == 0 THEN CX = 1 ; AND CX, CX ; JNZ CACh
0ADC:0CAC:
IF CX > AX THEN CX = AX ; CMP AX, CX ; JNC CB2h ; MOV CX, AX
BYTE PTR DS:[011C] += CL ; Cursor X position += CL
0ADC:0CB6:
CALL 1535h ; update cursor position on screen
0ADC:0CB9:
return
--
; ESC [ D
; SI = ANSI escape area (2852h)
0ADC:0CBA:
IF BYTE PTR DS:[0129] != 1 JMP CDCh
CX = WORD PTR DS:[SI]
0ADC:0CC3:
AX = BYTE PTR DS:[011C] ; Cursor X position
IF CX == 0 THEN CX = 1 ; AND CX, CX ; JNZ CCFh
IF CX > AX THEN CX = AX ; CMP AX, CX ; JNC CD5h ; MOV CX, AX
BYTE PTR DS:[011C] -= CL ; Cursor X position -= CL
0ADC:0CD9:
CALL 1535h ; update cursor position on screen
0ADC:0CDC:
return
--
; ESC [ L
; SI = ANSI escape area (2852h)
0ADC:0E3E:
IF BYTE PTR DS:[012A] != 0 JMP E63h
IF BYTE PTR DS:[0129] != 1 JMP E63h
0ADC:0E4C:
CX = WORD PTR DS:[SI]
0ADC:0E4E:
IF CX == 0 THEN CX = 1 ; AND CX, CX ; JNZ E55h
0ADC:0E55:
PUSH CX
AH = BYTE PTR DS:[0110] ; AH = Cursor Y position
CALL 13B4h
POP CX
IF CX > 0 THEN CX--, JMP E55h ; LOOP E55h
0ADC:0E60:
CALL 115Eh ; carriage return
0ADC:0E63:
BYTE PTR DS:[012A] = 0
0ADC:0E68:
return
--
; ESC [ M
; SI = ANSI escape area (2852h)
0ADC:0E69:
IF BYTE PTR DS:[0129] != 1 JMP E87h
CX = WORD PTR DS:[SI]
0ADC:0E72:
IF CX == 0 THEN CX = 1 ; AND CX, CX ; JNZ E55h
0ADC:0E79:
PUSH CX
AH = BYTE PTR DS:[0110] ; AH = Cursor Y position
CALL 135Fh
POP CX
IF CX > 0 THEN CX--, JMP E79h ; LOOP E79h
0ADC:0E84:
CALL 115Eh ; carriage return
0ADC:0E87:
return
--
; Entry: CL = character code
;
; This is executed on ESC [ >
0ADC:0E88:
BYTE PTR DS:[012A] = 1
return
--
; Entry: CL = character code
;
; This is executed on ESC [ ?
0ADC:0E8E:
BYTE PTR DS:[012A] = 2
return
--
; Entry: CL = character code
;
; This is executed on ESC [ =
0ADC:0E94:
BYTE PTR DS:[012A] = 3
return
--
; Entry: CL = character code
;
; This is executed when the ESC is encountered outside of ANSI processing
0ADC:10C1:
PUSH ES
WORD PTR DS:[0134] = 0x2852
BYTE PTR DS:[0128] = 0x01
BYTE PTR DS:[0129] = 0x01
DI = 0x2852
AX = 0
CX = 0x14
DX = ES = DS
_fmemset(ES:DI,0,0x28) ; REP STOSW
POP ES
0ADC:10E2:
return
--
; ??
0ADC:10E3:
CALL 10E7h
0ADC:10E6:
return far ; RETF
--
; ASCII BEL 07h handling
0ADC:10E7:
AH = 17h ; INT 18h AH=17h turn on bell
INT 18h
CX = 0x6E8C ; <- delay loop
0ADC:10EE:
PUSH AX
NOP AX
POP AX
IF CX > 0 THEN CX--, JMP 10EEh ; LOOP 10EEh
0ADC:10F3:
AH = 18h ; INT 18h AH=18h turn off bell
INT 18h
0ADC:10F7:
return
--
; ASCII TAB 09h handling
0ADC:10F8:
AL = ((BYTE PTR DS:[011C] + 8) >> 3) * 8 ; move cursor X position to next multiple of 8
BYTE PTR DS:[011C] = AL
IF AL < 0x4F JMP 1115h ; interesting bug here, AL would be 0x50 on overflow
0ADC:110C:
BYTE PTR DS:[011C] = 0x4F ; keep cursor on-screen, set to last column
CALL 118Ch ; call function to advance one column to wrap around to next line
return
0ADC:1115:
call 1535h ; update cursor position
0ADC:1118:
return
--
; ASCII BACKSPACE 08h / LEFT ARROW KEY
0ADC:1119:
IF BYTE PTR DS:[011C] == 0 JMP 1126h
0ADC:1120:
BYTE PTR DS:[011C] -= 1
JMP 1136h
0ADC:1126:
IF BYTE PTR DS:[0110] == 0 JMP 1139h
0ADC:112D:
BYTE PTR DS:[0110] -= 1
BYTE PTR DS:[011C] = 0x4F
0ADC:1136:
CALL 1535h ; update cursor position on screen
0ADC:1139:
return
--
; ASCII UP ARROW 0Bh
0ADC:113A:
IF BYTE PTR DS:[0110] == 0 JMP 1148h
BYTE PTR DS:[0110] -= 1
CALL 1535h ; update cursor position on screen
0ADC:1148:
return
--
; ASCII DOWN ARROW 0Ah
0ADC:1149:
AL = BYTE PTR DS:[0110]
IF AL == BYTE PTR DS:[0112] JMP 115Ah
BYTE PTR DS:[0110] += 1
CALL 1535h ; update cursor position on screen
return
0ADC:115A:
CALL 1348h ; scroll up screen region
return
--
; ASCII CARRIAGE RETURN 0Dh
0ADC:115E:
BYTE PTR DS:[011C] = 0 ; set X coordinate = 0
CALL 1535h ; update cursor position
0ADC:1166:
return
--
; ??
0ADC:1167:
CALL 116Bh
0ADC:116A:
return far ; RETF
--
; ASCII RECORD SEPARATOR 1Eh
0ADC:116B:
BYTE PTR DS:[0110] = 0 ; set Y pos = 0
BYTE PTR DS:[011C] = 0 ; set X pos = 0
CALL 1535h ; update cursor position
0ADC:1178:
return
--
0ADC:1179:
CALL 117Dh
0ADC:117C:
return far ; RETF
--
0ADC:117D: (CTRL+Z handling)
DI = 0
CX = 0x9B0 ; 0x9B0 = 80*31?
CALL 1516h ; clear the screen (fill with erasure)
CALL 13FFh ; remove function row
CALL 116Bh ; call 0x1E RECORD SEPARATOR function
0ADC:118B:
return
--
0ADC:118C: (advance cursor one column. if past right edge of screen fall through to 1197h to advance one row)
BYTE PTR DS:[011C] += 1 (cursor X coordinate += 1)
IF BYTE PTR DS:[011C] <= 4Fh JMP 11AFh (if cursor X coordinate <= 4Fh then goto 11AFh)
0ADC:1197: (advance cursor one row. if past lower scroll limit then fall through to 11A9h scroll up screen region)
BYTE PTR DS:[011C] = 0 (set cursor X coordinate = 0)
AL = BYTE PTR DS:[0110] (AL = (cursor Y coordinate)++)
BYTE PTR DS:[0110] += 1
IF BYTE PTR DS:[0112] != AL JMP 11AFh (if cursor Y != scroll range lower limit then goto 11AFh)
0ADC:11A9: (put cursor back on the bottom row and scroll screen region up)
BYTE PTR DS:[0110] = AL (set cursor Y coordinate to scroll range lower limit)
CALL 1348h
0ADC:11AF:
CALL 1535h (update cursor position on screen)
0ADC:11B2:
return
--
0ADC:11B3: (CL=10h AH=00h, at this time CL == caller's DL and DS = DOS segment 60h)
IF BYTE PTR DS:[011C] < 0x50 JMP 11C7h ; (60:11C cursor X position)
IF BYTE PTR DS:[0117] == 0 JMP 11C2h ; (60:117 line wrap flag)
0ADC:11C1:
return
0ADC:11C2:
PUSH CX
CALL 118Ch
POP CX
0ADC:11C7: (60:11C < 0x50)
IF BYTE PTR DS:[008A] == 0 JMP 1201h ; (60:8A kanji / graph mode flag)
IF BYTE PTR DS:[0115] != 0 JMP 11F3h ; (60:115 kanji upper byte storage flag)
IF CL < 0x81 JMP 1201h
IF CL < 0xA0 JMP 11E9h
IF CL < 0xE0 JMP 1201h
IF CL >= 0xFD JMP 1201h
BYTE PTR DS:[0116] = CL (60:116 kanji upper byte)
BYTE PTR DS:[0115] = 1 (60:115 kanji upper byte storage flag)
0ADC:11E9:
return
0ADC:11F3: (60:115 kanji upper byte storage flag set)
CH = DS:[0116] (60:116 kanji upper byte)
CALL 1236h
tCH = CH, tCL = CL, CL = tCH - 0x20, CH = tCL ; XCHG CL, CH ; SUB CL, 0x20
JMP 1203h
0ADC:1201:
CH = 0
0ADC:1203:
CALL 1260h
CALL 129Dh
DI = BX
AX = ((AX * 2) + DL) * 2
BX = (AX + 0A7Ch)
BX = WORD PTR CS:[BX]
PUSH ES
ES = WORD PTR DS:[0032] ; (60:32 appears to be Text VRAM segment A000h)
AX = CX
CALL NEAR BX
POP ES
BYTE PTR DS:[0115] = 0 (60:115 upper byte storage flag)
BYTE PTR DS:[011C] += AL (60:11C cursor X coordinate)
CALL 1535h
0ADC:1231:
return
--
0ADC:1232:
CALL 1236h
0ADC:1235:
return far ; RETF
--
0ADC:1236: (CH = upper Kanji byte)
IF CH == 0x80 JMP 125Fh
IF CH >= 0xA0 JMP 1245h
CH -= 0x70
JMP 1248h
0ADC:1245:
CH -= 0xB0
0ADC:1248:
IF (CL & 0x80) != 0x00 THEN CL-- ; OR CL, CL ; JNS 124E ; DEC CL
0ADC:124E:
CH = CH * 2
IF CL < 0x9E JMP 125Ah
CL -= 0x5E
JMP 125Ch
0ADC:125A:
CH--
0ADC:125C:
CL -= 0x1F
0ADC:125F:
return
--
0ADC:1260:
PUSH ES, CX
ES = WORD PTR DS:[0032] ; video ram segment (A000h)
DH = BYTE PTR DS:[0110] ; Cursor Y position
DL = BYTE PTR DS:[011C] ; Cursor X position
CALL 14F5h ; convert to video memory address (return in BX)
CX = WORD PTR ES:[BX] ; read from video memory
CALL 129Dh ; Determine cell width (single or double, indicated in DL)
AX = 2
IF DL == 1 JMP 129Ah
DH = DL
CX = WORD PTR ES:[BX+2]
CALL 129Dh
AX = 0
IF DH != 2 JMP 1294h
AX = 3
0ADC:1294:
IF DL == 0 JMP 129Ah
AX++
0ADC:129A:
POP CX, ES
0ADC:129C:
return
--
0ADC:129D:
DL = 0
IF CH == 0x00 JMP 12BBh
IF CH == 0xFF JMP 12BBh
IF CL < 0x09 JMP 12B3h
IF CL < 0x0C JMP 12BBh
0ADC:12B3:
DL = 1
IF (CL & 0x80) != 0 JMP 12BBh
DL = 2
0ADC:12BB:
return
--
0ADC:12BC: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
CALL 1330h
CALL 12E2h ; write single-wide
0ADC:12C2:
return
--
0ADC:12C3: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
CALL 1324h
CALL 12E2h ; write single-wide
0ADC:12C9:
return
--
0ADC:12CA: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
CALL 133Ch
CALL 12F2h ; write double-wide
0ADC:12D0:
return
--
0ADC:12D1: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
CALL 1324h
CALL 12F2h ; write double-wide
0ADC:12D7:
return
--
0ADC:12D8: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
CALL 1324h
CALL 133Ch
CALL 12F2h ; write double-wide
0ADC:12E1:
return
--
; This appears to write a single-wide character
0ADC:12E2: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
WORD PTR ES:[DI] = AX ; write character code
DI += 0x2000
WORD PTR ES:[DI] = WORD PTR DS:[013C] (60:13C display attribute in extended attribute mode) ; write attribute code
AL = 1 (this indicates to caller to move cursor X position 1 unit to the right)
0ADC:12F1:
return
--
; This appears to write a double-wide (two cell wide) character
0ADC:12F2: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
IF BYTE PTR DS:[011C] < 0x4F JMP 1311h ; if Cursor X coordinate < 0x4F
; NTS: Cursor wraparound case (no room on last column). Write an empty cell then wrap to the next line and print char.
PUSH AX
CX = 0x20, WORD PTR ES:[DI] = CX
CALL 118Ch ; advance cursor one column
DH = BYTE PTR DS:[0110] ; DH = cursor Y
DL = BYTE PTR DS:[011C] ; DL = cursor X
CALL 14F5h ; Convert DH, DL to VRAM address in BX
DI = BX
POP AX
; NTS: Notice the double-wide (usually Kanji) writing routine writes the code from AX, then
; writes AX | 0x80. This has no effect on the display on real hardware, but follows
; NEC PC-98 recommendations.
0ADC:1311:
WORD PTR ES:[DI] = AX, DI += 2 ; STOSW
WORD PTR ES:[DI] = AX | 0x80, DI += 2 ; OR AL,80h ; STOSW
DI -= 4, DI += 0x2000
AX = WORD PTR DS:[013C] ; AX = extended color attribute
WORD PTR ES:[DI] = AX, DI += 2 ; STOSW
WORD PTR ES:[DI] = AX, DI += 2 ; STOSW
AL = 2
0ADC:1323:
return
--
0ADC:1324: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
PUSH DI
DI -= 2
CX = 0x20
WORD PTR ES:[DI] = CX
POP DI
0ADC:132F:
return
--
0ADC:1330: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
PUSH DI
DI += 2
CX = 0x20
WORD PTR ES:[DI] = CX
POP DI
0ADC:133B:
return
--
0ADC:133C: (DS = DOS segment 60h, ES = Text VRAM segment A000h, AX = character code, DI = memory offset)
PUSH DI
DI += 4
CX = 0x20
WORD PTR ES:[DI] = CX
POP DI
0ADC:1347:
return
--
0ADC:1348: (scroll up screen scroll region)
AH = BYTE PTR DS:[011E] ; scroll region upper limit
WORD PTR DS:[011F] = 0x0001 ; scroll "weight" aka delay
IF BYTE PTR DS:[0118] != 0 THEN WORD PTR DS:[011F] = 0xE000 ; if slow scroll mode set "weight" aka delay to larger value
0ADC:135F:
CL = BYTE PTR DS:[0112] ; scroll region lower limit
CX = CL - AH ; lower limit - upper limit and zero extend to CX
if CX == 0 JMP 13A1h
0ADC:1369:
PUSH ES, DS
DX = AH << 8 ; DH = AH, DL = 0
CALL 14F5h ; take cursor position, convert to video RAM byte address, return in BX
ES = DS = WORD PTR DS:[0032] ; retrieve video (text) RAM segment
DX = BX + 0xA0 ; note 0xA0 = 160 = 80 * 2
0ADC:1381:
PUSH CX
; This part uses REP MOVSW first on character data at A000:0000+x
; then on attribute data at A000:2000+x
; Move and swap is used to let REP MOVSW advance SI and DI, then
; re-use the same starting SI and DI for the attribute data, before
; then using the post REP MOVSW SI and DI values for the next line.
SI = DX
DI = BX
_fmemcpy(ES:DI,DS:SI,0xA0) ; CX = 0x50 REP MOVSW
SWAP(DX,SI), SI += 0x2000
SWAP(BX,DI), DI += 0x2000
_fmemcpy(ES:DI,DS:SI,0xA0) ; CX = 0x50 REP MOVSW
POP CX
IF CX > 0 THEN CX--, JMP 1381h ; LOOP 1381h
0ADC:139F:
POP DS, ES
0ADC:13A1:
DH = BYTE PTR DS:[0112]
call 1508h
CX = WORD PTR DS:[011F]
0ADC:13AC: ; <- delay loop, to "weight" down the console scroll
NOP
IF CX > 0 THEN CX--, JMP 13ACh ; LOOP 13ACh
0ADC:13AF:
return
--
0ADC:13B0: (take scroll region, scroll down one line)
AH = BYTE PTR DS:[011E] ; scroll range upper limit
CL = BYTE PTR DS:[0112], CH = 0 ; scroll range lower limit
CL -= AH
IF CL == 0 THEN JMP 13F8h
0ADC:13BE:
STD ; set direction flag, so that REP MOVSW works backwards
PUSH ES, DS
DH = BYTE PTR DS:[0112]
DL = 0x4F
CALL 14F5h ; convert scroll lower limit row, column 0x4F (79) to video ram address
ES = DS = WORD PTR DS:[0032] ; video RAM segment
DX = BX - 0xA0 ; DX = video RAM address one row up, BX = video RAM address
0ADC:13D8:
PUSH CX
SI = DX, DI = BX
_fmemcpy_backwards(ES:DI, DS:SI, 0xA0) ; CX = 0x50, REP MOVSW, with DF=1
XCHG DX, SI ; XCHG BX, DI ; SI,DI modified by REP MOVSW, so swap with copy to re-use original addr for next step
SI += 0x2000 ; DI += 0x2000 ; point at attribute RAM
_fmemcpy_backwards(ES:DI, DS:SI, 0xA0) ; CX = 0x50, REP MOVSW, with DF=1
POP CX
IF CX > 0 THEN CX--, JMP 13D8h ; LOOP 13D8h
0ADC:13F6:
POP DS, ES ; CLD
DH = AH ; DH = scroll range upper limit
CALL 1508h
0ADC:13FE:
return
--
0ADC:13FF:
IF BYTE PTR DS:[0111] != 0 JMP 1407h
0ADC:1406:
return
0ADC:1407:
(TODO)
--
0ADC:14F5: (DH = Y coordinate DL = X coordinate return in BX = video RAM byte address)
BX = (WORD PTR DS:[(DH * 2) + 0x1814])
DX = (DL * 2)
BX += DX
return ; 0ADC:1507
--
0ADC:1508: (DH = Scroll range lower limit)
DL = 0
CALL 14F5h (get video RAM address of row DH from caller and column zero)
DI = BX
CX = 0x50
CALL 1516h
return
0ADC:1516: (CX = number of WORDs to write, DI = video ram address to fill)
PUSH ES
ES = WORD PTR DS:[0032] ; get video RAM (text) segment A000h
DX = CX ; save CX (for later)
BX = DI ; save DI (for later)
AX = WORD PTR DS:[0119] ; erasure character
_fmemset(ES:DI,cx*2) ; REP STOSW (CX from caller)
AX = WORD PTR DS:[013E] ; erasure attribute
CX = DX ; restore CX from caller
DI = BX + 0x2000 ; restore DI from caller and add 2000h
_fmemset(ES:DI,cx*2) ; REP STOSW (CX from caller)
POP ES
return
--
0ADC:1534:
return
0ADC:1535: (update cursor position on screen)
IF BYTE PTR DS:[011B] == 0 JMP 1534h (return immediately if cursor is turned off)
0ADC:153C:
DH = BYTE PTR DS:[0110]
DL = BYTE PTR DS:[011C]
IF DL >= 0x50 THEN DL--
0ADC:154B:
CALL 14F5h (take cursor position, convert to video RAM byte address, return in BX)
AH = 0x13 (INT 18h AX=13h set cursor position)
DX = BX (byte position of cursor)
JMP 198Ah (calls INT 18h AX=13h to set cursor pos. function 198Ah then returns)
--
0ADC:1814 Row value to video RAM address lookup table used by subroutine at 0ADC:14F5
VRAM_ADDRESS = WORD PTR [0ADC:1814 + (row * 2)]
. . . . . . . . <- Cursor rows 0-7
0060:00001814 00 00 A0 00 40 01 E0 01 80 02 20 03 C0 03 60 04 ....@..... ...`.
. . . . . . . . <- Cursor rows 8-15
0060:00001824 00 05 A0 05 40 06 E0 06 80 07 20 08 C0 08 60 09 ....@..... ...`.
. . . . . . . . <- Cursor rows 16-23
0060:00001834 00 0A A0 0A 40 0B E0 0B 80 0C 20 0D C0 0D 60 0E ....@..... ...`.
. . . . . . . |END <- Cursor rows 24-30
0060:00001844 00 0F A0 0F 40 10 E0 10 80 11 20 12 C0 12 00 00 ....@..... .....
--
0ADC:198A (this code calls INT 18h in an elaborate way in order to make sure interrupts are disabled at entry point for some reason)
PUSH DS
DS = 0
PUSHF, CLI, CALL FAR WORD PTR DS:[0060] (DS=0, CALL FAR 0000:0060, which is INT 18h but with interrupts disabled at entry)
POP DS
return
--
0ADC:3126:
PUSH DS
DS = WORD PTR CS:[0030] = DOS segment 60h
WORD PTR DS:[05E1] = caller DS
Store caller AX, SS, SP, DX, BX into DS: [5DB], [5DD], [5DF], [5E3], [5E5]
SS:SP = WORD PTR CS:[0030] (DOS segment 60h : offset 767h)
CLD, STI
PUSH ES, BX, CX, DX, SI, DI
BYTE PTR DS:[00B4] = 1
0ADC:3154:
CL -= 9, JMP to 0ADC:3180 if carry (if caller CL < 9)
0ADC:315E:
IF CL < 0x0D, JMP TO 0ADC:3173 (if caller CL < (0x16 = 0x0D+9))
0ADC:3163:
IF CL < 0x77, JMP TO 0ADC:3180 (if caller CL < (0x80 = 0x77+9))
0ADC:3168:
IF CL > 0x79, JMP TO 0ADC:3180 (if caller CL > (0x82 = 0x79+9))
0ADC:316D: (JMPed here if CL >= 0x80 && CL <= 0x82)
CL = (CL - 0x77) + 0x0D
0ADC:3173: (JMPed here if CL >= 0x09 && CL <= 0x15)
SI = (CL * 2) + 0x3A5C
0ADC:317D:
CALL NEAR WORD PTR 0ADC:[SI]
0ADC:3180:
CALL NEAR 0ADC:4080
0ADC:3183:
POP DI, SI, DX, CX, BX, ES
DS = WORD PTR CS:[0030] = DOS segment 60h
Restore caller AX, SS, SP, DX, BX from [5DB], [5DD], [5DF], [5E3], [5E5]
POP DS (restore caller DS)
IRET
--
0ADC:32DF: (CL=0Dh entry point)
ES = WORD PTR CS:[0030] ; MS-DOS segment (60h)
AX = WORD PTR DS:[05DB] ; AX from caller
DS = WORD PTR DS:[05E1] ; DS from caller
SI = DX ; DX from caller
IF AX > 0xFF JMP 32F7h ; CMP AX,00FF ; JA 32F7h
IF AX != 0xFF JMP 3310h ; ... JNE 3310h
JMP 3350h
0ADC:32F7: (AX > 0xFF)
IF AX < 0x101 JMP 3304h ; CMP AX,0101 ; JC 3304h
IF AX == 0x101 JMP 3308h ; ... JE 3308h
IF AX == 0x102 JMP 330Ch ; CMP AX,0102 ; JE 330Ch
0ADC:3303:
return
0ADC:3304: (AX < 0x101)
CALL 3445h
return
0ADC:3308: (AX == 0x101)
CALL 349Ch
return
0ADC:330C: (AX == 0x102)
CALL 3538h
return
0ADC:3310: (AX < 0xFF)
IF AX != 0 THEN AX--, JMP 3390h ; SUB AX, 1 ; JNC 3390h
0ADC:3315: (AX == 0, DS = caller DS segment, SI = caller DX register, ES = MS-DOS segment 60h)
DI = 2D2Eh ; This appears to be the memory location that holds the function key row strings and attributes
DL = 0Ah ; There are 10 entries, 16 bytes apart
0ADC:331A:
CALL 3547h ;
_fmemcpy(ES:DI, DS:SI, 0x0F) ; CX = 0x0F ; REP MOVSB
; Side effect: SI += 0x0F, DI += 0x0F
SI++
IF DL > 0 THEN DL--, JMP 331Ah ; DEC DL ; JNZ 331Ah
0ADC:3327:
DI += 0x50 ; Reminder: 2D2Eh + (0x10 * 0x0A) + 0x50 = 2E1Eh
; This (2E1Eh) appears to hold the text that is injected when the function key is pressed.
; For example by default this table defines F1 -> "DIR A:\x0D"
DL = 0Ah
0ADC:332C:
CALL 3547h
_fmemcpy(ES:DI, DS:SI, 0x0F) ; CX = 0x0F ; REP MOVSB
; Side effect: SI += 0x0F, DI += 0x0F
SI++
IF DL > 0 THEN DL--, JMP 332Ch ; DEC DL ; JNZ 332Ch
0ADC:3339:
DI += 0x50 ; Reminder: 2E1Eh + (0x10 * 0x0A) + 0x50 = 2F0Eh
DL = 0x0B
0ADC:333E:
CALL 3547h
_fmemcpy(ES:DI, DS:SI, 0x05) ; CX = 0x05 ; REP MOVSB
; Side effect: SI += 0x05, DI += 0x05
SI++
DI += 2
IF DL > 0 THEN DL--, JMP 333Eh ; DEC DL ; JNZ 333Eh
0ADC:334E:
JMP 3386h
0ADC:3350: (AX == 0xFF)
DI = 2D2Eh ; Memory location that appears to hold function key row strings
DL = 0x1E
0ADC:3355:
CALL 3547h
_fmemcpy(ES:DI, DS:SI, 0x0F) ; CX = 0x0F ; REP MOVSB
; Side effect: SI += 0x0F, DI += 0x0F
SI++
IF DL > 0 THEN DL--, JMP 3355h
0ADC:3362:
DL = 0x0B
0ADC:3364:
CALL 3547h
_fmemcpy(ES:DI, DS:SI, 0x05) ; CX = 0x05 ; REP MOVSB
; Side effect: SI += 0x05, DI += 0x05
DI += 2
IF DL > 0 THEN DL--, JMP 3364h
0ADC:3374:
DI = 0x2F86
DL = 0x0F
0ADC:3379:
CALL 3547h
_fmemcpy(ES:DI, DS:SI, 0x0F) ; CX = 0x0F ; REP MOVSB
SI++
IF DL > 0 THEN DL--, JMP 3379h
0ADC:3386:
IF BYTE PTR ES:[0111] == 0 THEN JMP 33ECh ; ES = DOS segment 60h
JMP 33ECh ; Wait... what?
0ADC:3390:
(TODO)
0ADC:33EC:
IF AX < 0x29 JMP 33E3h ; CMP AX, 29h ; JC 33E3h
IF AX > 0x39 JMP 33E3h ; CMP AX, 39h ; JA 33E3h
IF AX == 0x39 JMP 3417h ; ... JE 3417h
0ADC:33F8:
IF AX <= 0x32 JMP 3405h ; CMP AX, 32h ; JBE 3405h
IF AX != 0x38 JMP 33E3h ; CMP AX, 38h ; JNE 33E3h
0ADC:3402:
AX = 0x28
0ADC:3405:
DI = ((AX - 0x29) * 16) + 0x2F86
CX = 0x000F
JMP 33DEh
0ADC:3417:
AX = 0x38
PUSH DS, SI, DI
CALL 33F8h
POP DI, SI, DS
SI += 0x10
DI += 0x10
CX = 0x0A
0ADC:342C:
PUSH CX, DS, SI, DI
AX = 0x33 - CX
CALL 33F8h
POP DI, SI
DI += 0x10
SI += 0x10
POP DS, CX
IF CX > 0 THEN CX--, JMP 342Ch ; LOOP 342Ch
0ADC:3444:
return
0ADC:3445:
DI = 307Ah
SI += 2
AX = BX = 0
_fmemcpy(ES:DI, DS:SI, 0x200) ; CX = 0x200 ; REP MOVSB
0ADC:3454:
DI = 307Ah
CX = DI
CX += 0x200
IF DI >= CX JMP 346Fh ; CMP DI, CX ; JNC 346Fh
IF BYTE PTR ES:[DI] == 0 JMP 346Fh
AL = BYTE PTR ES:[DI] ; AH = 0 at this point
DI += AX
JMP 345Dh
0ADC:346F:
WORD PTR ES:[3076] = DI - 0x307A ; SUB DI, 307Ah ; MOV ES:[3076] DI
DI = 3078h
(TODO)
--
0ADC:355B: (CL=0Ah entry point)
IF WORD PTR DS:[1802] != 0 JMP 3563h
return
0ADC:3563: (CL=0Ah and WORD PTR DS:[1802] == 0)
IF (BYTE PTR DS:[0037] & 8) != 0 JMP 357Eh
0ADC:356A:
AH = 00h
INT 19h
CX = 0
IF AH == 0 JMP 3579h
CX = 0xFFFF
0ADC:3579:
WORD PTR DS:[05DB],CX (AX value to return to caller)
return
0ADC:357E:
IF (AH & 0xF0) != 0 JMP 3597h
BYTE PTR DS:[0068],DH
PUSH DX
DL = (DL AND 0x0F)
BYTE PTR DS:[0069] = (BYTE PTR DS:[0069] & 0xF0) | DL
POP DX
JMP 35A4h
0ADC:3597:
IF AH > 0x20 JMP 35A3h
IF WORD PTR DS:[17FA] != 0 JMP 35A4h
0ADC:35A3:
return
0ADC:35A4:
AH = (DL & 0x30)
BX = AH >> 3
ES = WORD PTR DS:[1802]
DI = WORD PTR ES:[BX+0x40]
AH = AH | 7
BX = 0
IF (DH & 1) == 0 JMP 35C9h
BH = BH | 0x30
0ADC:35C9:
AL = (DL & 0x0F) + 1
DH = ((DH & 0xFE) | 0x02)
0ADC:35D5:
IF (AH & 0x30) != 0 JMP 35E1h
IF (AL & 0x08) != 0 JMP 35E1h
DH = DH | 1
0ADC:35E1:
CH = DH
CL = 37h
AL = AL - 2
IF (CH & 0x04) != 0 JMP 35F1h
BH = BH | 0x40
0ADC:35F1:
DX = 0x0100
IF WORD PTR [F800:7FFC] == 0 JMP 3605h (IF WORD at memory address 0xFFFFC == 0)
DX = DX + 1
0ADC:3605:
PUSH AX
INT 19h, RESULT = AH
POP AX
IF RESULT == 0 JMP 3614h
WORD PTR DS:[05DB] = 0xFFFF (returned to caller as AX)
return
0ADC:3614:
WORD PTR DS:[05DB] = 0x0000 (returned to caller as AX)
return
--
0ADC:378E: (CL=10h entry point)
BX = WORD PTR DS:[05DB] caller's AX value
BX = (BX >> 8) (BX = caller's AH value)
ADDR = (BX * 4) + 3A7Ch
AX = WORD PTR CS:[ADDR] (0ADC:[ADDR])
BX = WORD PTR CS:[ADDR+2]
CALL NEAR AX
return
--
0ADC:37A7: (CL=10h AH=00h entry point)
CL = DL
CALL NEAR BX (BX is 0A9C, no other case)
0ADC:37AB:
return
--
0ADC:37AC: (CL=10h AH=01h entry point)
ES = WORD PTR DS:[05E1] ; caller's DS segment
BX = DX ; caller's DX register
0ADC:37B2:
CL = BYTE PTR ES:[BX]
IF CL == 0x24 JMP 37C2h ; stop at '$'
PUSH BX
CALL A9Ch
POP BX
INC BX
JMP 37B2h
0ADC:37C2:
return
--
0ADC:37C3: (CL=10h AH=02h entry point)
BYTE PTR DS:[011D],DL ; DL = caller's DL, assign to character attribute
WORD PTR DS:[013C],DX ; DX = caller's DX, assign to extended character attribute
return
--
0ADC:37CC: (CL=10h AH=03h entry point)
DX += 0x2020 ; DX = caller's DX add 0x20 to both bytes
swap(DL,DH) ; XCHG DL, DH
CX = DX
CALL WORD PTR CS:[BX] ; BX = 0x0AFA in all cases, which then feeds the "ESC =" handling code
return
--
0ADC:37D7: (CL=10h AH=04h entry point, where BX = 0x0B90 aka the "ESC D" handler)
(CL=10h AH=05h entry point, where BX = 0x0B99 aka the "ESC M" handler)
CALL WORD PTR CS:[BX] ; BX = 0x0B90 or BX = 0x0B99
return
--
0ADC:37DA: (CL=10h AH=06h entry point, where BX = 0x0C52 aka the "ESC [ A" handler)
(CL=10h AH=07h entry point, where BX = 0x0C75 aka the "ESC [ B" handler)
(CL=10h AH=08h entry point, where BX = 0x0C9C aka the "ESC [ C" handler)
(CL=10h AH=09h entry point, where BX = 0x0CC3 aka the "ESC [ D" handler)
(CL=10h AH=0Ch entry point, where BX = 0x0E4E aka the "ESC [ L" handler)
(CL=10h AH=0Dh entry point, where BX = 0x0E72 aka the "ESC [ M" handler)
DH = 0
CX = DX
CALL WORD PTR CS:[BX]
return
--
0ADC:37E1: (CL=10h AH=0Ah entry point, where BX = 0x0D2E)
(CL=10h AH=0Bh entry point, where BX = 0x0D72)
DH = 0
AX = DX
CALL WORD PTR CS:[BX]
return
--
0ADC:3A5C array of WORD values, offsets of procedures for each value of CL.
0ADC:3A5C table contents.
Note the INT DCh code maps:
CL = 0x09..0x15 to table index 0x00..0x0C
CL = 0x80..0x82 to table index 0x0D..0x0F
. . . . . . . .
0ADC:00003A5C B8 3A 5B 35 A4 31 A5 31 DF 32 1B 36 44 37 8E 37
. . . . . . . . |END
0ADC:00003A6C F0 37 6E 38 F7 38 85 3B 52 3C 27 39 B5 39 10 3A
CL = 0x09 0x3AB8
CL = 0x0A 0x355B
CL = 0x0B 0x31A4
CL = 0x0C 0x31A5
CL = 0x0D 0x32DF
CL = 0x0E 0x361B
CL = 0x0F 0x3744
CL = 0x10 0x378E
CL = 0x11 0x37F0
CL = 0x12 0x386E
CL = 0x13 0x38F7
CL = 0x14 0x3B85
CL = 0x15 0x3C52
CL = 0x80 0x3927
CL = 0x81 0x39B5
CL = 0x82 0x3A10
--
0ADC:3A7C array of WORD value pairs (address, parameter). NOTE: Lack of range checking!
Lookup table for CL=10h, index by AH
. . . .
0ADC:00003A7C A7 37 9C 0A AC 37 00 00 C3 37 00 00 CC 37 FA 0A .7...7...7...7..
. . . .
0ADC:00003A8C D7 37 90 0B D7 37 99 0B DA 37 52 0C DA 37 75 0C .7...7...7R..7u.
. . . .
0ADC:00003A9C DA 37 9C 0C DA 37 C3 0C E1 37 2E 0D E1 37 72 0D .7...7...7...7r.
. . . . |END?
0ADC:00003AAC DA 37 4E 0E DA 37 72 0E E8 37 2D 0B 8B 16 E3 05 .7N..7r..7-.....
? ? ? ?
0ADC:00003ABC A1 DB 05 3D 00 00 74 10 3D 01 00 74 20 3D 10 00 ...=..t.=..t =..
? ? ? ?
0ADC:00003ACC 74 4E 3D 11 00 74 49 C3 8E 06 E1 05 8B FA 2E 8E tN=..tI.........
0ADC:3A7C Call table (address, param)
Calling convention on entry: AX = subroutine address, BX = param
AH = 0x00 0x37A7 0x0A9C ; 0ADC:00003A7C
AH = 0x01 0x37AC 0x0000
AH = 0x02 0x37C3 0x0000
AH = 0x03 0x37CC 0x0AFA
AH = 0x04 0x37D7 0x0B90 ; 0ADC:00003A8C
AH = 0x05 0x37D7 0x0B99
AH = 0x06 0x37DA 0x0C52
AH = 0x07 0x37DA 0x0C75
AH = 0x08 0x37DA 0x0C9C ; 0ADC:00003A9C
AH = 0x09 0x37DA 0x0CC3
AH = 0x0A 0x37E1 0x0D2E
AH = 0x0B 0x37E1 0x0D72
AH = 0x0C 0x37DA 0x0E4E ; 0ADC:00003AAC
AH = 0x0D 0x37DA 0x0E72
AH = 0x0E 0x37E8 0x0B2D
AH = 0x0F 0x168B 0x05E3
--
0ADC:3AB8: (INT DCh CL=0x09) [DS=0x0060 DOS SEGMENT]
DX = WORD PTR DS:[05E3] (caller DX)
AX = WORD PTR DS:[05DB] (caller AX)
IF AX == 0x0000 JMP 3AD4h
IF AX == 0x0001 JMP 3AE9h
IF AX == 0x0010 JMP 3B1Ch
IF AX == 0x0011 JMP 3B1Ch
0ADC:3AD3:
return
0ADC:3AD4: (INT DCh CL=0x09 AX=0x0000)
ES = WORD PTR DS:[05E1] (caller DS)
DI = DX (caller DX)
DS = WORD PTR CS:[0030] (DOS segment 60h)
SI = 1DBBh
_fmemcpy(ES:DI,DS:SI,8)
return
0ADC:3AE9: (INT DCh CL=0x09 AX=0x0001)
WORD PTR DS:[05DB] = 0xFFFF (caller AX set to 0xFFFF)
IF BYTE PTR DS:[1DC4] == 0 JMP 3B1Bh
DL = DL AND 0x0F
BX = 26Ah
CX = (WORD)BYTE PTR DS:[1DC4] * 4
0ADC:3B06:
IF BYTE PTR DS:[BX+2] != DL JMP 3B15h
BYTE PTR DS:[BX+1] = 2
WORD PTR DS:[05DB] = 0x0000 (caller AX set to 0x0000)
BX += WORD PTR DS:[0268]
IF CX > 0 THEN CX--, JMP 3B06h
0ADC:3B1B:
return
0ADC:3B1C: (INT DCh CL=0x09 AX=0x0010 or AX=0x0011)
WORD PTR DS:[05DB] = 0xFFFF (caller AX set to 0xFFFF)
IF BYTE PTR DS:[1DC4] == 0 JMP 3B84h
DX = DX AND 0xFF
CX = 0x1A
BX = 2C86h
0ADC:3B31:
IF BYTE PTR DS:[BX+1] == DL JMP 3B3Fh
BX += 2
DH += 1
IF CX > 0 THEN CX--, JMP 3B31h
JMP 3B84h
0ADC:3B3F:
IF (BYTE PTR DS:[BX] AND 1) == 0 JMP 3B84h
BYTE PTR DS:[0136] = DH (set last access drive number)
IF AX != 0x0010 JMP 3B52h
CALL 5B07h
JMP 3B69h
0ADC:3B52:
WORD PTR DS:[05DB] = 0x0001 (caller AX set to 0x0001)
BX = DL & 0x0F
IF BYTE PTR [BX+03E9h] == 0 JMP 3B84h
CALL 5B4Bh, RESULT = CARRY FLAG
0ADC:3B69:
WORD PTR DS:[05DB] = 0x0000
IF RESULT == 0 (CF=0) JMP 3B84h
WORD PTR DS:[05DB] = 0x0002
IF BYTE PTR DS:[025B] == 2 JMP 3B84h
WORD PTR DS:[05DB] = 0x0003
0ADC:3B84:
return
--
Called from 0ADC:3180 (near)
0ADC:4080:
CLI
PUSH DS
DS = DOS kernel segment 60h from 0ADC:0030
BYTE PTR DS:[00B4] = 0
0ADC:408C:
IF BYTE PTR DS:[00A5] != 01h JMP 40ACh
0ADC:4093:
IF BYTE PTR DS:[00A6] == 01h JMP 40A2h
0ADC:409A:
STI
PUSH AX
CALL 40AFh
POP AX
POP DS
return
0ADC:40A2:
BYTE PTR DS:[00A5] = 0x00
BYTE PTR DS:[00A6] = 0x00
0ADC:40AC:
STI
POP DS
return
0ADC:40AF:
IF WORD PTR DS:[2A7C] == 0h JMP 40C6h
0ADC:40B6:
PUSH DS
WORD PTR DS:[2A7A] = 0x18
CALL FAR 0060h:3C6Fh
NOP
NOP
NOP
POP DS
0ADC:40C6:
return