Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
20939 lines (20938 sloc) 905 KB
F000:0000 ;
F000:0000 ; º This file is generated by The Interactive Disassembler (IDA) º
F000:0000 ; º Copyright (c) 2010 by Hex-Rays SA, <> º
F000:0000 ; º Licensed to: Freeware version º
F000:0000 ;
F000:0000 ; Input MD5 : C66B49CD7082D1B81442FB2704542401
F000:0000 ; File Name : Z:\Users\riq\progs\ibm_pcjr-bios\rom\bios-f0000-fffff.bin
F000:0000 ; Format : Binary file
F000:0000 ; Base Address: F000h Range: F0000h - 100000h Loaded length: 10000h
F000:0000 .8086
F000:0000 .model small
F000:0000 ; Segment type: Pure code
F000:0000 F000 segment byte public 'CODE'
F000:0000 a1504036Copr_Ibm19811 db '1504036 COPR. IBM 1981,1983'
F000:001B z1 dw offset l12 ; return pointers for rtns called before stack is initialized
F000:001D dw offset l14
F000:001F dw offset l16
F000:0021 dw offset l19
F000:0023 dw offset l24
F000:0025 f3b db ' KB' ; DATA XREF: q35+36o
F000:0028 ex_0 dw offset eb0 ; DATA XREF: e_msg+83o
F000:002A dw offset eb0
F000:002C dw offset totlpt0
F000:002E ex1 dw offset mo1 ; DATA XREF: e_msg+BFo
F000:0030 ;----------------------------------------------------
F000:0030 ; message area for post
F000:0030 ;----------------------------------------------------
F000:0030 error_err db 'ERROR' ; DATA XREF: e_msg+25o
F000:0035 mem_err db 'A'
F000:0036 key_err db 'B' ; DATA XREF: key_scan_save+16o
F000:0037 cass_err db 'C'
F000:0038 com1_err db 'D'
F000:0039 com2_err db 'E'
F000:003A rom_err db 'F'
F000:003B cart_err db 'G'
F000:003C disk_err db 'H' ; DATA XREF: F000:086Fo
F000:003D f4 dw 378h ; DATA XREF: F000:f15co
F000:003D ; print source table
F000:003F dw 278h
F000:0041 imasks dw 0F7EFh ; DATA XREF: uart:at1o
F000:0041 ; interrupt masks for 8259 interrupt controllers
F000:0043 ;----------------------------------------------------
F000:0043 ; setup
F000:0043 ; disable nmi, maskable ints.
F000:0043 ; sound chip, and video.
F000:0043 ; turn drive 0 motor off
F000:0043 ;----------------------------------------------------
F000:0043 reset: ; CODE XREF: F000:f19_0j
F000:0043 ; kb_int+10Dj kb_int+11Aj
F000:0043 ; F000:E05Bj F000:loc_FFFF0J
F000:0043 mov al, 0
F000:0045 out 0A0h, al ; disables nmi
F000:0047 dec al ; send ff to mfg_tester
F000:0049 out 10h, al
F000:004B in al, 0A0h ; reset nmi f/f
F000:004D cli ; disable maskable interrupts
F000:004D ; disable attenuation in sound chip
F000:004E mov ax, 108Fh ; reg address in ah, attenuator in off
F000:004E ; in al
F000:0051 mov dx, 0C0h ; 'À' ; address of sound chip
F000:0054 mov cx, 4 ; 4 attenuators to disable
F000:0057 l1: ; CODE XREF: kb_int-1504j
F000:0057 or al, ah ; combine reg address and data
F000:0059 out dx, al
F000:005A add ah, 20h ; ' ' ; point to next reg
F000:005D loop l1
F000:005F mov al, 0A0h ; ' ' ; turn drive 0 motor off, enable timer
F000:0061 out 0F2h, al
F000:0063 mov dx, 3DAh ; video gate array control
F000:0066 in al, dx ; sync vga to accept reg
F000:0067 mov al, 4 ; set vga reset reg
F000:0069 out dx, al ; select it
F000:006A mov al, 1 ; set async reset
F000:006C out dx, al ; reset video gate array
F000:006D ;----------------------------------------------------
F000:006D ; test 1
F000:006D ; 8088 processor test
F000:006D ; description
F000:006D ; verify 8088 flags, registers
F000:006D ; and conditional jumps
F000:006D ;
F000:006D ; mfg. error code 0001h
F000:006D ;----------------------------------------------------
F000:006D mov ah, 0D5h ; 'Õ'
F000:006F sahf
F000:0070 loc_F0070: ; DATA XREF: diag_bios_break+5r
F000:0070 jnb short l4
F000:0072 jnz short l4
F000:0074 jnp short l4
F000:0076 jns short l4
F000:0078 lahf
F000:0079 mov cl, 5
F000:007B shr ah, cl
F000:007D jnb short l4
F000:007F loc_F007F: ; DATA XREF: timer_int+38o
F000:007F mov al, 40h ; '@'
F000:0081 shl al, 1
F000:0083 loc_F0083: ; DATA XREF: sub_F5DB5+Cw
F000:0083 ; sub_F5DB5+25r
F000:0083 jno short l4
F000:0085 xor ah, ah
F000:0087 sahf
F000:0088 jbe short l4
F000:008A js short l4
F000:008C jp short l4
F000:008E lahf
F000:008F mov cl, 5
F000:0091 shr ah, cl
F000:0093 jb short l4
F000:0095 shl ah, 1
F000:0097 jo short l4
F000:0099 ;----- read/write the 8088 general and segmentation registers
F000:0099 ; with all one's and zeroes's
F000:0099 mov ax, 0FFFFh
F000:009C stc
F000:009D l2: ; CODE XREF: kb_int-14A9j
F000:009D mov ds, ax
F000:009F mov bx, ds
F000:00A1 mov es, bx
F000:00A3 mov cx, es
F000:00A5 mov ss, cx
F000:00A7 mov dx, ss
F000:00A9 mov sp, dx
F000:00AB mov bp, sp
F000:00AD mov si, bp
F000:00AF mov di, si
F000:00B1 jnb short l3
F000:00B3 xor ax, di
F000:00B5 jnz short l4
F000:00B7 clc
F000:00B8 jmp short l2
F000:00BA l3: ; CODE XREF: kb_int-14B0j
F000:00BA or ax, di
F000:00BC jz short l5
F000:00BE l4: ; CODE XREF: kb_int:loc_F0070j
F000:00BE ; kb_int-14EFj kb_int-14EDj
F000:00BE ; kb_int-14EBj kb_int-14E4j
F000:00BE ; kb_int:loc_F0083j ...
F000:00BE mov dx, 10h
F000:00C1 mov al, 0
F000:00C3 out dx, al
F000:00C4 inc dx
F000:00C5 out dx, al
F000:00C6 inc al
F000:00C8 out dx, al
F000:00C9 hlt
F000:00CA ;----------------------------------------------------
F000:00CA ; test 2
F000:00CA ; 8522 initialization and test
F000:00CA ; description
F000:00CA ; first initialize 8255 prog.
F000:00CA ; peripheral interface. ports a&b
F000:00CA ; are latched output
F000:00CA ; buffers. c is input.
F000:00CA ;
F000:00CA ; mfg. err. code =0002h
F000:00CA ;----------------------------------------------------
F000:00CA l5: ; CODE XREF: kb_int-14A5j
F000:00CA mov al, 0FEh ; 'þ'
F000:00CC out 10h, al ; send fe to mfg
F000:00CE mov al, 10001001b
F000:00D0 out 63h, al ; configures i/o ports (63h = cmd_port)
F000:00D2 sub ax, ax ; test pattern seed = 0000
F000:00D4 l6: ; CODE XREF: kb_int-147Dj
F000:00D4 mov al, ah
F000:00D6 out 60h, al ; write pattern port port a
F000:00D8 in al, 60h ; read pattern from port a
F000:00DA out 61h, al ; write pattern to port b
F000:00DC in al, 61h ; read output port
F000:00DE cmp al, ah ; data as expected?
F000:00E0 jnz short l7 ; if not, something is wrong
F000:00E2 inc ah ; make new data pattern
F000:00E4 jnz short l6 ; loop till 255 data patterns done
F000:00E6 jmp short l8 ; continue if done
F000:00E8 l7: ; CODE XREF: kb_int-1481j
F000:00E8 mov bl, 2
F000:00EA jmp e_msg
F000:00ED l8: ; CODE XREF: kb_int-147Bj
F000:00ED xor al, al
F000:00EF out 60h, al ; clear kb port
F000:00F1 in al, 62h
F000:00F3 and al, 8 ; 64k card present?
F000:00F5 mov al, 1Bh ; port setting for 64k sys
F000:00F7 jnz short l9
F000:00F9 mov al, 3Fh ; '?' ; port setting for 128k sys
F000:00FB l9: ; CODE XREF: kb_int-146Aj
F000:00FB mov dx, 3DFh
F000:00FE out dx, al
F000:00FF mov al, 1101b ; initialize output ports
F000:0101 out 61h, al
F000:0103 ;----------------------------------------------------
F000:0103 ; Part 3
F000:0103 ; set up video gate array and 6845 to get memory working
F000:0103 ;
F000:0103 ;----------------------------------------------------
F000:0103 mov al, 0FDh ; 'ý'
F000:0105 out 10h, al
F000:0107 mov dx, 3D4h ; set address of 6845
F000:010A mov bx, offset video_parms ; point to 6845 parms
F000:010D mov cx, 10h ; set parm len
F000:0110 nop
F000:0111 xor ah, ah ; ah is reg #
F000:0113 l10: ; CODE XREF: kb_int-1442j
F000:0113 mov al, ah ; get 6845 reg #
F000:0115 out dx, al
F000:0116 inc dx ; point to data port
F000:0117 inc ah ; next reg value
F000:0119 mov al, cs:[bx] ; get table value
F000:011C out dx, al ; out to chip
F000:011D inc bx ; next in table
F000:011E dec dx ; back to pointer reg
F000:011F loop l10
F000:0121 mov dx, 3DAh ; set address of vga
F000:0124 in al, dx ; be sure addr/data flag is in the proper state
F000:0125 mov cx, 5 ; # of registers
F000:0128 xor ah, ah ; ah is reg counter
F000:012A l11: ; CODE XREF: kb_int-142Fj
F000:012A mov al, ah ; get reg #
F000:012C out dx, al ; select it
F000:012D xor al, al ; set zero for data
F000:012F out dx, al
F000:0130 inc ah ; next reg
F000:0132 loop l11
F000:0134 ;----------------------------------------------------
F000:0134 ; test 4
F000:0134 ; planar board ros checksum test
F000:0134 ; description
F000:0134 ; a checksum test is done for each ros
F000:0134 ; module on the planar board to.
F000:0134 ; mfg error code =0003h module at address
F000:0134 ; f000:0000 error
F000:0134 ; 0004h module at address
F000:0134 ; f800:0000 error
F000:0134 ;----------------------------------------------------
F000:0134 mov al, 0FCh ; 'ü'
F000:0136 out 10h, al ; mfg out = fc
F000:0138 ; check module at f000:0 (lenght 32k)
F000:0138 xor si, si
F000:013A mov ax, cs
F000:013C mov ss, ax
F000:013E mov ds, ax
F000:0140 mov cx, 8000h
F000:0143 mov sp, 1Bh
F000:0146 jmp ros_checksum
F000:0146 ; END OF FUNCTION CHUNK FOR kb_int
F000:0149 l12: ; DATA XREF: F000:z1o
F000:0149 jz short l13
F000:014B mov bx, 3
F000:014E jmp e_msg
F000:0151 l13: ; CODE XREF: F000:l12j
F000:0151 mov cx, 8000h
F000:0154 jmp ros_checksum
F000:0157 l14: ; DATA XREF: F000:001Do
F000:0157 jz short l15
F000:0159 mov bx, 4 ; indicate error
F000:015C jmp e_msg
F000:015F ;----------------------------------------------------
F000:015F ; test 5
F000:015F ; base 2k read/write storage test
F000:015F ; description
F000:015F ; write/read/verify data patterns
F000:015F ; aa,55 and 00 to 1st 2k of storage
F000:015F ; and the 2k just below 64k (crt buffer)
F000:015F ; verify storage addressability.
F000:015F ; on exit set crt page to 3. set
F000:015F ; temporary stack also.
F000:015F ; mfg. error code 04xx for system board mem.
F000:015F ; 05xx for 64k attrib. cd. mem
F000:015F ; 06xx for error in both
F000:015F ; (xx= error bits)
F000:015F ;----------------------------------------------------
F000:015F l15: ; CODE XREF: F000:l14j
F000:015F mov al, 0FBh ; 'û'
F000:0161 out 10h, al ; set mfg flag = fb
F000:0163 mov cx, 400h
F000:0166 xor ax, ax
F000:0168 mov es, ax ; load es with 0000 segment
F000:016A jmp podstg
F000:016D l16: ; DATA XREF: F000:001Fo
F000:016D jnz short l20 ; bad storage found
F000:016F mov al, 0FAh ; 'ú' ; mfg out = fa
F000:0171 out 10h, al
F000:0173 mov cx, 400h ; 1024 words to be tested in the regen buffer
F000:0176 in al, 60h ; where is the regen buffer?
F000:0178 cmp al, 1Bh ; top of 64k?
F000:017A mov ax, 0F80h ; set pointer to there if it is (0xf800)
F000:017D jz short l18
F000:017F mov ah, 1Fh ; or set pointer to top of 128k (0x1f800)
F000:0181 l18: ; CODE XREF: F000:017Dj
F000:0181 mov es, ax
F000:0183 jmp podstg
F000:0186 l19: ; DATA XREF: F000:0021o
F000:0186 jz short l23
F000:0188 l20: ; CODE XREF: F000:l16j
F000:0188 mov bh, 4 ; error 04
F000:018A in al, 62h ; get config bits
F000:018C and al, 8 ; test for attrib card present
F000:018E jz short l21 ; worry about odd/even if it is
F000:0190 mov bl, cl
F000:0192 or bl, ch ; cobine error bits if it isn't
F000:0194 jmp short l22
F000:0196 l21: ; CODE XREF: F000:018Ej
F000:0196 cmp ah, 2 ; even byte error? err 04xx
F000:0199 mov bl, cl
F000:019B jz short l22
F000:019D inc bh ; make into 05xx err
F000:019F or bl, ch ; move and possible combine error bits
F000:01A1 cmp ah, 1 ; odd byte error
F000:01A4 jz short l22
F000:01A6 inc bh ; must have been both - make into 06hh
F000:01A8 l22: ; CODE XREF: F000:0194j
F000:01A8 ; F000:019Bj F000:01A4j
F000:01A8 jmp e_msg ; jump to error output routine
F000:01AB ; retest high 2k using b8000 address path
F000:01AB l23: ; CODE XREF: F000:l19j
F000:01AB mov al, 0F9h ; 'ù' ; mfg out=f9
F000:01AD out 10h, al
F000:01AF mov cx, 400h ; 1k words
F000:01B2 mov ax, 0BB80h ; point to area just tested with direct addressing
F000:01B5 mov es, ax
F000:01B7 jmp podstg
F000:01BA l24: ; DATA XREF: F000:0023o
F000:01BA jz short l25
F000:01BC mov bx, 5
F000:01BF jmp e_msg
F000:01C2 l25: ; CODE XREF: F000:l24j
F000:01C2 mov ax, 30h ; '0'
F000:01C5 mov ss, ax
F000:01C7 mov sp, 100h
F000:01CA xor ax, ax
F000:01CC mov ds, ax
F000:01CE ;----- setup crt page
F000:01CE mov word ptr ds:462h, 7 ; 40:62 (active page)
F000:01D4 ;----- set preliminary memory size word
F000:01D4 mov bx, 64
F000:01D7 in al, 62h
F000:01D9 and al, 8 ; 64k card present?
F000:01DB mov al, 1Bh ; port system for 64k system
F000:01DD jnz short l26
F000:01DF add bx, 64 ; else set for 128k
F000:01E2 mov al, 3Fh ; '?' ; port setting for 128k system
F000:01E4 l26: ; CODE XREF: F000:01DDj
F000:01E4 mov ds:415h, bx ; 40:15 (true_mem)
F000:01E8 mov ds:48Ah, al ; 40:8a (pagdat)
F000:01EB ;----------------------------------------------------
F000:01EB ; part 6
F000:01EB ; interrupts
F000:01EB ; description
F000:01EB ; 32 interrupts are initialized to point to a
F000:01EB ; dummy handler. the bios interrupts are loaded.
F000:01EB ; diagnostics interrupts are loaded
F000:01EB ; system configuration word is put in memory.
F000:01EB ; the dummy interrupt handler resides here.
F000:01EB ;----------------------------------------------------
F000:01EB mov ax, 50h ; 'P'
F000:01EE mov ds, ax
F000:01F0 mov byte ptr ds:seg50.mfg_tst, 0F8h ; 'ø' ; set up mfg checkpoint from this point
F000:01F5 call mfg_up ; update mfg checkpoint
F000:01F8 mov word ptr ds:seg50.mfg_rtn, offset mfg_out
F000:01FE mov ax, cs
F000:0200 mov ds:seg50.mfg_ret_s, ax ; set doubleword pointer to mfg.
F000:0200 ; error output routine so diags
F000:0200 ; don't have to duplicate code
F000:0203 mov ax, 0
F000:0206 mov ds, ax
F000:0208 ;----- set up the interrupt vectors to temp interrupt
F000:0208 mov cx, 0FFh ; first all interrupts
F000:020B sub di, di ; first interrupt location is 0000
F000:020D mov es, di ; set es=0000 also
F000:020F d3: ; CODE XREF: F000:0216j
F000:020F mov ax, offset d11 ; move addr of intr proc seg
F000:0212 stosw
F000:0213 mov ax, cs ; get addr of intr proc seg
F000:0215 stosw
F000:0216 loop d3 ; vectbl0
F000:0218 mov word ptr ds:124h, offset extab ; set up ekt. scan table (int 0x49)
F000:021E ;----- set up bios interrupts
F000:021E mov di, 40h ; '@' ; set up video int (int 0x10)
F000:0221 push cs
F000:0222 pop ds ; place cs in ds
F000:0223 mov si, offset vector_table_16
F000:0226 mov cx, 16 ; 16 entries
F000:0229 d4: ; CODE XREF: F000:022Cj
F000:0229 movsw ; move interrupt vector to low memory
F000:022A inc di
F000:022B inc di ; point to next vector entry
F000:022C loop d4 ; repeat for all 16 bios interrupts
F000:022E ;----- set up diagnostics interrupts
F000:022E mov di, 200h ; start with int 80h
F000:0231 mov si, offset diag_table_ptr ; point to entry point table
F000:0234 mov cx, 16 ; 16 entries
F000:0237 d5: ; CODE XREF: F000:023Aj
F000:0237 movsw ; move interrupt vector to low memory
F000:0238 inc di
F000:0239 inc di ; point to next vector entry
F000:023A loop d5 ; repeat for all 16 bios interrupts
F000:023C mov ds, cx ; set ds to zero
F000:023E mov word ptr ds:204h, offset locate_1_int_81 ; int 0x81
F000:0244 mov word ptr ds:208h, offset prtn3_int_82 ; int 0x82
F000:024A mov word ptr ds:224h, offset int_89_diag_joystick ; int 0x89
F000:0250 ;----- set up default equipment determination word
F000:0250 ; bit 15,14 = number of printers attached
F000:0250 ; bit 13 = 1 = serial printer present
F000:0250 ; bit 12 = game i/o attached
F000:0250 ; bit 11,10,9 = number of rs232 cards attached
F000:0250 ; bit 8 = dma (0=dma present, 1=no dma on system)
F000:0250 ; bit 7,6 = number of diskette drives
F000:0250 ; 00=1, 01=2, 10=3, 11=4 only if bit 0 = 1
F000:0250 ; bit 5,4 = initial video mode
F000:0250 ; 00 - unused
F000:0250 ; 01 - 40x25 bw using color card
F000:0250 ; 10 - 80x25 bw using color card
F000:0250 ; 11 - 80x25 bw using bw card
F000:0250 ; bit 3,2 = planar ram size (10=48k, 11=64k)
F000:0250 ; bit 1 not used
F000:0250 ; bit 0 = 1 (ipl diskette installed)
F000:0250 ;----------------------------------------------------
F000:0250 mov bx, 1118h ; default gameio, 40x25, no dma, 48k on planar
F000:0253 in al, 62h
F000:0255 and al, 8 ; 64k card present
F000:0257 jnz short d55 ; no, jump
F000:0259 or bl, 4 ; set 64k on planar
F000:025C d55: ; CODE XREF: F000:0257j
F000:025C mov ds:410h, bx ; 0:410 = 40:10 = equip flag
F000:0260 ;----------------------------------------------------
F000:0260 ; test 7
F000:0260 ; initialize and test the 8259 interrupt controller chip
F000:0260 ; mfg err. code 07xx (xx=00, data path or internal failure,
F000:0260 ; xx=any other bits on=unexpected interrupts
F000:0260 ;----------------------------------------------------
F000:0260 call mfg_up ; mfg code=f7
F000:0263 mov al, 10011b ; icw1 - reset edge sense circuit, set single 8259 chip and icw4 read
F000:0265 out 20h, al
F000:0267 mov al, 8 ; icw2 - set interrupt type 8 (8-f)
F000:0269 out 21h, al
F000:026B mov al, 1001b ; icw4 - set buffered mode/slave and 8086 mode
F000:026D out 21h, al
F000:026F ;----------------------------------------------------
F000:026F ; test ability to write/read the mask register
F000:026F ;----------------------------------------------------
F000:026F mov al, 0 ; write zeroes to imr
F000:0271 mov bl, al ; preset error indicator
F000:0273 out 21h, al ; device interrupts enabled
F000:0275 in al, 21h ; read imr
F000:0277 or al, al ; imr = 0?
F000:0279 jnz short gerror ; no - go to error routine
F000:027B mov al, 0FFh ; disable device interrupts
F000:027D out 21h, al ; write ones to imr
F000:027F in al, 21h ; read imr
F000:0281 add al, 1 ; all imr bits on? (add should produce 0)
F000:0283 jnz short gerror ; no - go to error routine
F000:0285 ;----------------------------------------------------
F000:0285 ; check for hot interrupts
F000:0285 ;----------------------------------------------------
F000:0285 sti
F000:0286 mov cx, 50h ; 'P'
F000:0289 hot1: ; CODE XREF: F000:hot1j
F000:0289 loop hot1
F000:028B mov bl, ds:484h ; 0:484 == 40:84 == intr_flag. did any interrupts occur?
F000:028F or bl, bl
F000:0291 jz short end_testg
F000:0293 gerror: ; CODE XREF: F000:0279j
F000:0293 ; F000:0283j
F000:0293 mov bh, 7
F000:0295 jmp e_msg
F000:0298 ; fire the diskette watchdog timer
F000:0298 end_testg: ; CODE XREF: F000:0291j
F000:0298 mov al, 0E0h ; 'à'
F000:029A out 0F2h, al
F000:029C mov al, 0A0h ; ' '
F000:029E out 0F2h, al
F000:02A0 ;----- initialize timer 1 and timer 0 for test
F000:02A0 call mfg_up ; mfg ckpoint=f6
F000:02A3 mov ax, 176h ; set timer 1 to mode 3 binary
F000:02A6 mov bx, 0FFFFh ; initial count of ffff
F000:02A9 call init_timer ; initialize timer 1
F000:02AC mov ax, 110110b ; set timer 0 to mode 3 binary
F000:02AF call init_timer ; initialize timer 0
F000:02B2 ;----------------------------------------------------
F000:02B2 ; set bit 5 of port a0 so timer 1 clock will be pulsed by the
F000:02B2 ; timer 0 output rather than the system clock
F000:02B2 ;----------------------------------------------------
F000:02B2 mov al, 100000b ; (timer 0 output used as clk input for timer 1)
F000:02B4 out 0A0h, al
F000:02B6 ;----------------------------------------------------
F000:02B6 ; check if all bits go on an off in timer 0 (check for stuck
F000:02B6 ; bits)
F000:02B6 ;----------------------------------------------------
F000:02B6 mov ah, 0 ; timer 0
F000:02B8 call bits_on_off ; let subroutine check it
F000:02BB jnb short timer1_nz ; no stuck bits (carry flag not set)
F000:02BD mov bl, 0 ; stuck bits in timer 0
F000:02BF jmp timer_error
F000:02C2 ;----------------------------------------------------
F000:02C2 ; since timer 0 has completed at least one complete cycle,
F000:02C2 ; timer 1 should be non-zero. check that this is the case.
F000:02C2 ;----------------------------------------------------
F000:02C2 timer1_nz: ; CODE XREF: F000:02BBj
F000:02C2 in al, 41h ; read lsb of timer 1
F000:02C4 mov ah, al ; save lsb
F000:02C6 in al, 41h ; read msb of timer 1
F000:02C8 cmp ax, 0FFFFh ; still ffff?
F000:02CB jnz short timer0_intr ; no - timer 1 has been bumped
F000:02CD mov bl, 1 ; timer 1 was not bumped by timer 0
F000:02CF jmp timer_error
F000:02D2 ;----------------------------------------------------
F000:02D2 ; check for timer 0 interrupt
F000:02D2 ;----------------------------------------------------
F000:02D2 timer0_intr: ; CODE XREF: F000:02CBj
F000:02D2 sti ; enable maskable ext interrupts
F000:02D3 in al, 21h
F000:02D5 and al, 0FEh ; mask all intrs except lvl 0
F000:02D7 and ds:484h, al ; clear int received
F000:02DB out 21h, al ; write the 8259 imr
F000:02DD mov cx, 0FFFFh ; set loop count
F000:02E0 wait_intr_loop: ; CODE XREF: F000:02E7j
F000:02E0 test byte ptr ds:484h, 1 ; timer 0 int occur?
F000:02E5 jnz short reset_intrs ; yes - continue
F000:02E7 loop wait_intr_loop ; wait for interrupt for specified time
F000:02E9 mov bl, 2 ; timer 0 intr didn't occur
F000:02EB jmp short timer_error
F000:02ED ;----------------------------------------------------
F000:02ED ; housekeeping for timer 0 interrupts
F000:02ED ;----------------------------------------------------
F000:02ED reset_intrs: ; CODE XREF: F000:02E5j
F000:02ED cli
F000:02EE ; set timer int. to point to mfg. heartbeat routine if in mfg mode
F000:02EE mov dx, 201h
F000:02F1 in al, dx ; get mfg. bits
F000:02F2 and al, 0F0h
F000:02F4 cmp al, 10000b ; sys test mode?
F000:02F6 jz short d6
F000:02F8 or al, al ; or burn-in mode
F000:02FA jnz short time_1
F000:02FC d6: ; CODE XREF: F000:02F6j
F000:02FC mov word ptr ds:20h, offset mfg_tick ; set to point to mfg. (int 0x08)
F000:0302 mov word ptr ds:70h, offset mfg_tick ; also set user timer int for diags. use (int 0x1c)
F000:0308 mov al, 0FEh ; 'þ'
F000:030A out 21h, al ; (enable lvl 0 interrupt)
F000:030C sti
F000:030D ;----------------------------------------------------
F000:030D ; reset d5 of port a0 so that the timer 1 clock will be
F000:030D ; pulsed by the system clock
F000:030D ;----------------------------------------------------
F000:030D time_1: ; CODE XREF: F000:02FAj
F000:030D mov al, 0 ; make al = 0
F000:030F out 0A0h, al
F000:0311 ;----------------------------------------------------
F000:0311 ; check for stuck bits in timer 1
F000:0311 ;----------------------------------------------------
F000:0311 mov ah, 1 ; timer 1
F000:0313 call bits_on_off
F000:0316 jnb short timer2_init ; no stuck bits
F000:0318 mov bl, 3 ; stuck bits in timer 1
F000:031A jmp short timer_error
F000:031C ;----------------------------------------------------
F000:031C ; initialize timer 2
F000:031C ;----------------------------------------------------
F000:031C timer2_init: ; CODE XREF: F000:0316j
F000:031C mov ax, 2B6h ; set timer 2 to mode 3 binary
F000:031F mov bx, 0FFFFh ; initial count
F000:0322 call init_timer
F000:0325 ;----------------------------------------------------
F000:0325 ; set pb0 of port_b of 8255 (timer 2 gate)
F000:0325 ;----------------------------------------------------
F000:0325 in al, 61h ; current status
F000:0327 or al, 1 ; set bit 0, others alone
F000:0329 out 61h, al
F000:032B mov ah, 2
F000:032D call bits_on_off
F000:0330 jnb short reinit_t2
F000:0332 mov bl, 5
F000:0334 jmp short timer_error
F000:0336 reinit_t2: ; CODE XREF: F000:0330j
F000:0336 in al, 61h
F000:0338 and al, 0FEh
F000:033A out 61h, al
F000:033C mov ax, 2B0h
F000:033F mov bx, 0Ah
F000:0342 call init_timer
F000:0345 in al, 62h
F000:0347 and al, 20h
F000:0349 jz short ck2_on
F000:034B mov bl, 4
F000:034D jmp short timer_error
F000:034F ck2_on: ; CODE XREF: F000:0349j
F000:034F in al, 61h
F000:0351 or al, 1
F000:0353 out 61h, al
F000:0355 mov cx, 0Ah
F000:0358 ck2_lo: ; CODE XREF: F000:ck2_loj
F000:0358 loop ck2_lo
F000:035A in al, 62h
F000:035C and al, 20h
F000:035E jnz short pod_13_end
F000:0360 mov bl, 6
F000:0362 timer_error: ; CODE XREF: F000:02BFj
F000:0362 ; F000:02CFj F000:02EBj
F000:0362 ; F000:031Aj F000:0334j
F000:0362 ; F000:034Dj
F000:0362 mov bh, 8 ; timer error indicator
F000:0364 call e_msg
F000:0367 jmp short pod_13_end
F000:0369 latches db 0 ; DATA XREF: bits_on_off+9o
F000:0369 ; latch mask for timer 0
F000:036A db 40h ; @ ; latch mask for timer 1
F000:036B db 80h ; € ; latch mask for timer 2
F000:036C bits_on_off proc near ; CODE XREF: F000:02B8p
F000:036C ; F000:0313p F000:032Dp
F000:036C xor bx, bx
F000:036E xor si, si
F000:0370 mov dx, 40h ; '@'
F000:0373 add dl, ah
F000:0375 mov di, offset latches
F000:0378 xor al, al
F000:037A xchg al, ah
F000:037C add di, ax
F000:037E outer_loop: ; CODE XREF: bits_on_off+47j
F000:037E mov cx, 8
F000:0381 inner_loop: ; CODE XREF: bits_on_off+3Ej
F000:0381 push cx
F000:0382 mov cx, 0FFFFh
F000:0385 tst_bits: ; CODE XREF: bits_on_off+3Bj
F000:0385 mov al, cs:[di] ; timer latch mask index
F000:0388 out 43h, al ; latch timer
F000:038A push ax ; pause
F000:038B pop ax
F000:038C in al, dx ; read timer lsb
F000:038D or si, si
F000:038F jnz short second ; second pass
F000:0391 or al, 1
F000:0393 or bl, al
F000:0395 in al, dx
F000:0396 or bh, al
F000:0398 cmp bx, 0FFFFh
F000:039C jmp short tst_cmp
F000:039E second: ; CODE XREF: bits_on_off+23j
F000:039E and bl, al
F000:03A0 in al, dx
F000:03A1 and bh, al
F000:03A3 or bx, bx
F000:03A5 tst_cmp: ; CODE XREF: bits_on_off+30j
F000:03A5 jz short chk_end
F000:03A7 loop tst_bits
F000:03A9 pop cx
F000:03AA loop inner_loop
F000:03AC stc
F000:03AD retn
F000:03AE chk_end: ; CODE XREF: bits_on_off:tst_cmpj
F000:03AE pop cx
F000:03AF inc si
F000:03B0 cmp si, 2
F000:03B3 jnz short outer_loop
F000:03B5 clc
F000:03B6 retn
F000:03B6 bits_on_off endp
F000:03B7 ;----------------------------------------------------
F000:03B7 ; crt attachment test
F000:03B7 ; 1. init crt to 40x25 - bw
F000:03B7 ; 2. check for vertical and video enables, and check
F000:03B7 ; timing of same
F000:03B7 ; 3. check vertical interrupt
F000:03B7 ; 4. check red, green, blue and intensify dots
F000:03B7 ; 5. init to 40x25 - color
F000:03B7 ; mfg. error code 09xx (xx-see comments in code)
F000:03B7 ;----------------------------------------------------
F000:03B7 pod_13_end: ; CODE XREF: F000:035Ej
F000:03B7 ; F000:0367j
F000:03B7 call mfg_up ; mfg checkpoint=f5
F000:03BA cli
F000:03BB mov al, 1110000b ; set timer 1 to mode 0
F000:03BB ; (tim 1, lsb/msb, interrupt on terminal count, binary)
F000:03BD out 43h, al
F000:03BF mov cx, 8000h
F000:03C2 q1: ; CODE XREF: F000:q1j
F000:03C2 loop q1 ; wait for mode set to "take"
F000:03C4 mov al, 0
F000:03C6 out 41h, al ; send first byte to timer
F000:03C8 sub ax, ax ; set mode 40x25 bw
F000:03CA int 10h
F000:03CC mov ax, 507h ; set video page 7
F000:03CF int 10h
F000:03D1 mov dx, 3DAh ; set addressing to video array
F000:03D4 sub cx, cx
F000:03D6 ; look for vertical
F000:03D6 q2: ; CODE XREF: F000:03DBj
F000:03D6 in al, dx ; get status
F000:03D7 test al, 8 ; vertical there yet?
F000:03D9 jnz short q3 ; continue if it is
F000:03DB loop q2
F000:03DD mov bl, 0
F000:03DF jmp short q115 ; no vertical = error 0900
F000:03E1 ; got vertical - start timer
F000:03E1 q3: ; CODE XREF: F000:03D9j
F000:03E1 xor al, al
F000:03E3 out 41h, al ; send 2nd byte to timer to start
F000:03E5 sub bx, bx ; init. enable counter
F000:03E7 ; wait for vertical to go away
F000:03E7 xor cx, cx
F000:03E9 q4: ; CODE XREF: F000:03EEj
F000:03E9 in al, dx ; get status
F000:03EA test al, 8 ; vertical still there?
F000:03EC jz short q5 ; continue if it's gone
F000:03EE loop q4
F000:03F0 mov bl, 1 ; vertical stuck on = error 0901
F000:03F2 jmp short q115
F000:03F4 ; now start looking for enable transitions
F000:03F4 q5: ; CODE XREF: F000:03ECj
F000:03F4 ; F000:041Fj
F000:03F4 sub cx, cx
F000:03F6 q6: ; CODE XREF: F000:03FFj
F000:03F6 in al, dx ; get status
F000:03F7 test al, 1 ; enable on yet?
F000:03F9 jnz short q7 ; go on if it is
F000:03FB test al, 8 ; vertical on again?
F000:03FD jnz short q11 ; continue if it is
F000:03FF loop q6 ; keep looking if not
F000:0401 mov bl, 2
F000:0403 jmp short q115 ; enable stuck off = error 0902
F000:0405 ; make sure vertical went off with enable going on
F000:0405 q7: ; CODE XREF: F000:03F9j
F000:0405 test al, 8 ; vertical off?
F000:0407 jz short q8 ; go on if it is
F000:0409 mov bl, 3
F000:040B jmp short q115 ; vertical stuck on = error 0903
F000:040D ; now wait for enable go to off
F000:040D q8: ; CODE XREF: F000:0407j
F000:040D sub cx, cx
F000:040F q9: ; CODE XREF: F000:0414j
F000:040F in al, dx ; get status
F000:0410 test al, 1 ; enable off yet?
F000:0412 jz short q10 ; proceed if it is
F000:0414 loop q9 ; keep looking if not yet low
F000:0416 mov bl, 4
F000:0418 jmp short q115
F000:041A ; enable has toggled , bump counter and test for next vertical
F000:041A q10: ; CODE XREF: F000:0412j
F000:041A inc bx ; bump enable counter
F000:041B jz short q11 ; if counter wraps, error
F000:041D test al, 8 ; did enable go low because of vertical?
F000:041F jz short q5 ; if not, look for another enable toggle
F000:0421 ; have had complete vertical-vertical cycle, now test results
F000:0421 q11: ; CODE XREF: F000:03FDj
F000:0421 ; F000:041Bj
F000:0421 mov al, 1000000b ; latch timer1
F000:0421 ; (tim 1, latching, interrupt on terminal count, binary)
F000:0423 out 43h, al
F000:0425 cmp bx, 200 ; number of enables between verticals o.k.?
F000:0429 jz short q12
F000:042B mov bl, 5
F000:042D q115: ; CODE XREF: F000:03DFj
F000:042D ; F000:03F2j F000:0403j
F000:042D ; F000:040Bj F000:0418j
F000:042D jmp short q22 ; wrong # enables = error 0905
F000:042F q12: ; CODE XREF: F000:0429j
F000:042F in al, 41h ; get timer value low
F000:0431 mov ah, al ; save it
F000:0433 nop
F000:0434 in al, 41h ; get timer high
F000:0436 xchg ah, al
F000:0438 sti ; interrupts back on
F000:0439 nop
F000:043A cmp ax, 0A0ACh ; (0xb286 * 0.9)
F000:043A ; there are 0x4dc8 PIT cycles per screen (262*76)
F000:043A ; and 0x10000-0xb286 = 0x4d7a... a few PIT cycles short... but good enough
F000:043D jge short q13
F000:043F mov bl, 6
F000:0441 jmp short q22 ; verticals too far appart
F000:0441 ; = error 0906
F000:0443 q13: ; CODE XREF: F000:043Dj
F000:0443 cmp ax, 0C460h ; (0xb286 * 1.1)
F000:0446 jle short q14
F000:0448 mov bl, 7
F000:044A jmp short q22 ; verticals too close together
F000:044A ; = error 0907
F000:044C ; timings seem o.k., now check vertical interrupt (level 5)
F000:044C q14: ; CODE XREF: F000:0446j
F000:044C sub cx, cx ; set timeout reg
F000:044E in al, 21h
F000:0450 and al, 11011111b ; unmask int. level 5
F000:0452 out 21h, al
F000:0454 and ds:484h, al ; intr flag
F000:0458 sti ; enable ints
F000:0459 q15: ; CODE XREF: F000:0460j
F000:0459 test byte ptr ds:484h, 20h ; see if intr. 5 happened yet
F000:045E jnz short q16 ; go on if it did
F000:0460 loop q15 ; keep looking if it didn't
F000:0462 mov bl, 8
F000:0464 jmp short q22 ; no vertical interrupt = error 0908
F000:0466 q16: ; CODE XREF: F000:045Ej
F000:0466 in al, 21h ; disable interrupts for level 5
F000:0468 or al, 20h
F000:046A out 21h, al
F000:046C ; see if red, green, blue and intesify dots work
F000:046C ; first, set a line of reverse video, intensified blanksinto video
F000:046C ; buffer
F000:046C mov ax, 9DBh ; write chars, blocks
F000:046F mov bx, 77Fh ; page 7, reverse video, high intensity
F000:0472 mov cx, 40 ; 40 characters
F000:0475 int 10h
F000:0477 xor ax, ax ; start with blue dots
F000:0479 q17: ; CODE XREF: F000:04A1j
F000:0479 sub cx, cx
F000:047B out dx, al ; set video array address for dots
F000:047C ; see if dot comes on
F000:047C q18: ; CODE XREF: F000:0481j
F000:047C in al, dx ; get status
F000:047D test al, 10h ; dot there?
F000:047F jnz short q19 ; go look for dot to turn off
F000:0481 loop q18 ; continue testing for dot on
F000:0483 mov bl, 10h
F000:0485 or bl, ah ; or in dot being tested
F000:0487 jmp short q22 ; dot not coming on = error 091x
F000:0487 ; ( x=0, blue; x=1, green;
F000:0487 ; x=2, red;, x=3, intensity)
F000:0489 ; see if dot comes off
F000:0489 q19: ; CODE XREF: F000:047Fj
F000:0489 sub cx, cx
F000:048B q20: ; CODE XREF: F000:0490j
F000:048B in al, dx ; get status
F000:048C test al, 10h ; is dot still on?
F000:048E jz short q21 ; go on if dot off
F000:0490 loop q20 ; else, keep waiting for dot to go off
F000:0492 mov bl, 20h ; ' '
F000:0494 or bl, ah ; or in dot being tested
F000:0496 jmp short q22 ; dot stuck on = error 092x
F000:0496 ; ( x=0, blue; x=1, green;
F000:0496 ; x=2, red; x=3 intensity)
F000:0498 ; adjust to point to next dot
F000:0498 q21: ; CODE XREF: F000:048Ej
F000:0498 inc ah
F000:049A cmp ah, 4 ; all for dots gone?
F000:049D jz short q23 ; go end
F000:049F mov al, ah
F000:04A1 jmp short q17 ; go look for another dot
F000:04A3 q22: ; CODE XREF: F000:q115j
F000:04A3 ; F000:0441j F000:044Aj
F000:04A3 ; F000:0464j F000:0487j
F000:04A3 ; F000:0496j
F000:04A3 mov bh, 9 ; set msb of error code
F000:04A5 jmp e_msg
F000:04A8 ; done with test reset to 40x25 - color
F000:04A8 q23: ; CODE XREF: F000:049Dj
F000:04A8 call dss
F000:04AB mov ax, 1 ; init to 40x25 - color
F000:04AE int 10h
F000:04B0 mov ax, 507h ; set video page 7
F000:04B3 int 10h
F000:04B5 cmp word ptr ds:seg40.reset_flag, 1234h ; warm start?
F000:04BB jz short q24 ; bypass putting up power-on screen
F000:04BD call put_logo ; put logo on screen
F000:04C0 q24: ; CODE XREF: F000:04BBj
F000:04C0 mov al, 1110110b ; re-init timer 1
F000:04C0 ; (tim 1, read/load lsb/msb, square, binary)
F000:04C2 out 43h, al
F000:04C4 mov al, 0
F000:04C6 out 41h, al
F000:04C8 nop
F000:04C9 nop
F000:04CA out 41h, al
F000:04CC call mfg_up ; mfg checkpoint=f4
F000:04CF xor ax, ax
F000:04D1 mov ds, ax
F000:04D3 mov word ptr ds:8, offset kdbnmi ; set interrupt vector (int 0x2)
F000:04D9 mov word ptr ds:120h, offset key_scan_save ; set vector for pod int handler (int 0x48)
F000:04DF loc_F04DF:
F000:04DF push cs
F000:04E0 loc_F04E0:
F000:04E0 pop ax
F000:04E1 loc_F04E1: ; (int 0x48 segment)
F000:04E1 mov ds:122h, ax
F000:04E4 loc_F04E4: ; set data segment
F000:04E4 call dss
F000:04E7 mov si, 1Eh
F000:04EA mov ds:seg40.buffer_head, si
F000:04EE mov ds:seg40.buffer_tail, si
F000:04F2 mov ds:seg40.buffer_start, si
F000:04F6 add si, 32 ; set default buffer of 32 bytes
F000:04F9 mov ds:seg40.buffer_end, si
F000:04FD in al, 0A0h ; clear nmi f/f
F000:04FF mov al, 10000000b ; enable nmi
F000:0501 out 0A0h, al
F000:0503 call mfg_up ; mfg checkpoint=f3
F000:0506 mov bx, 64 ; start with base 64k
F000:0509 in al, 62h ; get config byte
F000:050B test al, 8 ; see if 64k card installed
F000:050D jnz short q25
F000:050F add bx, 64 ; add 64k
F000:0512 q25: ; CODE XREF: F000:050Dj
F000:0512 push bx ; save k count
F000:0513 sub bx, 16 ; substract 16k crt refresh space
F000:0516 mov ds:seg40.memory_size, bx ; load "contiguous memory" word
F000:051A pop bx
F000:051B mov dx, 2000h ; set pointer to just about 128k
F000:051E sub di, di ; set di to point to beginning
F000:0520 mov cx, 0AA55h ; load data pattern
F000:0523 q26: ; CODE XREF: F000:053Bj
F000:0523 mov es, dx ; set segment to point to memory space
F000:0525 mov es:[di], cx ; set data pattern to memory
F000:0528 mov al, 0Fh
F000:052A mov ax, es:[di]
F000:052D xor ax, cx ; see if data made it back
F000:052F jnz short q27 ; no? then end of mem has been reached
F000:0531 add dx, 1000h ; point to beginning of next 64k
F000:0535 add bx, 40h ; '@' ; adjust total mem counter
F000:0538 cmp dh, 0A0h ; ' ' ; past 640 yet?
F000:053B jnz short q26 ; check for another block if not
F000:053D q27: ; CODE XREF: F000:052Fj
F000:053D mov ds:seg40.true_mem, bx ; load "total memory" word
F000:0541 ; size has been determined, now test or clear all of memory
F000:0541 mov ax, 4 ; 4 kb known ok at this point
F000:0544 call q35
F000:0547 mov dx, 80h ; '€' ; set pointer to just about lower 2k
F000:054A mov cx, 7800h ; test 30k words (60k)
F000:054D q28: ; CODE XREF: F000:0595j
F000:054D mov es, dx
F000:054F push cx
F000:0550 push bx
F000:0551 push ax
F000:0552 call podstg ; test of fill mem
F000:0555 jz short q29
F000:0557 jmp q39 ; jump if error
F000:055A q29: ; CODE XREF: F000:0555j
F000:055A pop ax
F000:055B pop bx
F000:055C pop cx ; recover
F000:055D cmp ch, 78h ; 'x' ; was this a 60k pass
F000:0560 pushf
F000:0561 add ax, 3Ch ; '<' ; bump good storage by 60k
F000:0564 popf
F000:0565 jz short q30
F000:0567 add ax, 2 ; add 2 for a 62k pass
F000:056A q30: ; CODE XREF: F000:0565j
F000:056A call q35
F000:056D cmp ax, bx ; are we done yet?
F000:056F jnz short q31
F000:0571 jmp q43 ; all done, if so
F000:0574 q31: ; CODE XREF: F000:056Fj
F000:0574 cmp ax, 128 ; done with 1st 128k?
F000:0577 jz short q32 ; go finish rest of mem.
F000:0579 mov dx, 0F80h ; set pointer to finish 1st 64 kb
F000:057C mov cx, 400h
F000:057F mov es, dx
F000:0581 push ax
F000:0582 push bx
F000:0583 push dx
F000:0584 call podstg ; go test/fill
F000:0587 jnz short q39
F000:0589 pop dx
F000:058A pop bx
F000:058B pop ax
F000:058C add ax, 2 ; update good count
F000:058F mov dx, 1000h ; set pointer to 2nd 64k block
F000:0592 mov cx, 7C00h ; 62k worth
F000:0595 jmp short q28
F000:0597 q32: ; CODE XREF: F000:0577j
F000:0597 mov dx, 2000h ; point to block about 128k
F000:059A q33: ; CODE XREF: F000:05BAj
F000:059A cmp bx, ax ; compare good mem to total mem
F000:059C jnz short q34
F000:059E jmp q43 ; exit if all done
F000:05A1 q34: ; CODE XREF: F000:059Cj
F000:05A1 mov cx, 4000h ; set for 32kb block
F000:05A4 mov es, dx
F000:05A6 push ax
F000:05A7 push bx
F000:05A8 push dx
F000:05A9 call podstg ; go test/fill
F000:05AC jnz short q39
F000:05AE pop dx
F000:05AF pop bx
F000:05B0 pop ax
F000:05B1 add ax, 32 ; bump good memory count
F000:05B4 call q35 ; display current good mem
F000:05B7 add dh, 8 ; set pointer to next 32k
F000:05BA jmp short q33 ; and make another pass
F000:05BC ; subroutine for printing tested
F000:05BC ; memory ok msg on the crt
F000:05BC ; call params: ax = x of good memory
F000:05BC ; (in hex)
F000:05BC q35 proc near ; CODE XREF: F000:0544p
F000:05BC ; F000:q30p F000:05B4p
F000:05BC call dss
F000:05BF cmp word ptr ds:seg40.reset_flag, 1234h
F000:05C5 jz short q35e
F000:05C7 push bx
F000:05C8 push cx
F000:05C9 push dx
F000:05CA push ax
F000:05CB mov ah, 2
F000:05CD mov dx, 1421h ; row 20 (row 20, col. 33)
F000:05D0 mov bh, 7
F000:05D2 int 10h ; - VIDEO - SET CURSOR POSITION
F000:05D2 ; DH,DL = row, column (0,0 = upper left)
F000:05D2 ; BH = page number
F000:05D4 pop ax
F000:05D5 push ax
F000:05D6 mov bx, 0Ah
F000:05D9 mov cx, 3
F000:05DC q36: ; CODE XREF: q35+28j
F000:05DC xor dx, dx
F000:05DE div bx
F000:05E0 or dl, 30h
F000:05E3 push dx
F000:05E4 loop q36
F000:05E6 mov cx, 3
F000:05E9 q37: ; CODE XREF: q35+31j
F000:05E9 pop ax
F000:05EA call prt_hex
F000:05ED loop q37
F000:05EF mov cx, 3
F000:05F2 mov si, offset f3b ; print " kb"
F000:05F5 q38: ; CODE XREF: q35+40j
F000:05F5 mov al, cs:[si]
F000:05F8 inc si
F000:05F9 call prt_hex
F000:05FC loop q38
F000:05FE pop ax
F000:05FF pop dx
F000:0600 pop cx
F000:0601 pop bx
F000:0602 q35e: ; CODE XREF: q35+9j
F000:0602 retn
F000:0602 q35 endp
F000:0603 q39: ; CODE XREF: F000:0557j
F000:0603 ; F000:0587j F000:05ACj
F000:0603 pop dx
F000:0604 cmp dx, 2000h
F000:0608 jl short q40
F000:060A mov bl, cl
F000:060C or bl, ch
F000:060E mov cl, 4
F000:0610 shr dh, cl
F000:0612 mov bh, 10h
F000:0614 or bh, dh
F000:0616 jmp short q42
F000:0618 q40: ; CODE XREF: F000:0608j
F000:0618 mov bh, 0Ah
F000:061A in al, 62h
F000:061C and al, 8
F000:061E jz short q41
F000:0620 mov bl, cl
F000:0622 or bl, ch
F000:0624 jmp short q42
F000:0626 q41: ; CODE XREF: F000:061Ej
F000:0626 cmp ah, 2
F000:0629 mov bl, cl
F000:062B jz short q42
F000:062D inc bh
F000:062F or bl, ch
F000:0631 cmp ah, 1
F000:0634 jz short q42
F000:0636 inc bh
F000:0638 q42: ; CODE XREF: F000:0616j
F000:0638 ; F000:0624j F000:062Bj
F000:0638 ; F000:0634j
F000:0638 mov si, 35h ; '5'
F000:063B call e_msg
F000:063E cli
F000:063F hlt
F000:0640 ; keyboard test
F000:0640 q43: ; CODE XREF: F000:0571j
F000:0640 ; F000:059Ej
F000:0640 call mfg_up ; mfg code=f2
F000:0643 call dss
F000:0646 mov bx, 1Eh
F000:0649 mov al, [bx]
F000:064B or al, al
F000:064D jz short f6_y
F000:064F mov bh, 22h ; '"'
F000:0651 mov bl, al
F000:0653 jmp short f6
F000:0655 f6_y: ; CODE XREF: F000:064Dj
F000:0655 cmp byte ptr ds:seg40.kdb_error, 0
F000:065A jz short f7
F000:065C mov bx, 2000h
F000:065F f6: ; CODE XREF: F000:0653j
F000:065F ; F000:06FCj
F000:065F mov si, 36h ; '6'
F000:0662 cmp word ptr ds:seg40.reset_flag, 4321h ; warm start to diags
F000:0668 jz short f6_z ; do not put up message
F000:066A cmp word ptr ds:seg40.reset_flag, 1234h ; warm system start
F000:0670 jz short f6_z ; do not put up message
F000:0672 call e_msg ; pritn msg on screen
F000:0675 f6_z: ; CODE XREF: F000:0668j
F000:0675 ; F000:0670j
F000:0675 jmp f6_x
F000:0678 ;check link card, if present
F000:0678 f7: ; CODE XREF: F000:065Aj
F000:0678 mov dx, 201h
F000:067B in al, dx ; check for burn-in mode
F000:067C and al, 0F0h
F000:067E jz short f6_x ; bypass check in burn-in mode
F000:0680 in al, 62h ; get config port data
F000:0682 and al, 10000000b ; keyboard cable attached?
F000:0684 jz short f6_x ; bypass test if it is
F000:0686 in al, 61h
F000:0688 and al, 11111100b ; drop speaker data
F000:068A out 61h, al
F000:068C mov al, 10110110b ; mode set timer 2
F000:068C ; (tim 2, read/load lsb/msb, square, binary)
F000:068E out 43h, al
F000:0690 mov al, 1000000b ; disable nmi
F000:0692 out 0A0h, al
F000:0694 mov al, 32 ; lsb to timer 2 (approx. 40khz vaue)
F000:0696 mov dx, 42h ; 'B'
F000:0699 out dx, al
F000:069A sub ax, ax
F000:069C mov cx, ax
F000:069E out dx, al ; msb to timer 2 (start timer)
F000:069F in al, 61h
F000:06A1 or al, 1
F000:06A3 out 61h, al ; enable timer 2
F000:06A5 f7_0: ; CODE XREF: F000:06ABj
F000:06A5 in al, 62h ; see if keyboard data active
F000:06A7 and al, 40h ; '@'
F000:06A9 jnz short f7_1 ; exit loop if data showed up
F000:06AB loop f7_0
F000:06AD mov bl, 2 ; set no keyboard data error
F000:06AF jmp short f6_1
F000:06B1 f7_1: ; CODE XREF: F000:06A9j
F000:06B1 push es ; save es
F000:06B2 sub ax, ax ; set up segment reg
F000:06B4 mov es, ax ; *
F000:06B6 mov word ptr es:8, offset d11 ; set up new nmi vector
F000:06BD mov ds:seg40.intr_flag, al ; reset intr. flag
F000:06C0 in al, 61h ; disable internal beeper to
F000:06C2 or al, 30h ; prevent error beep
F000:06C4 out 61h, al
F000:06C6 mov al, 11000000b
F000:06C8 out 0A0h, al ; enable nmi
F000:06CA mov cx, 100h
F000:06CD f6_0: ; CODE XREF: F000:f6_0j
F000:06CD loop f6_0 ; wait a bit
F000:06CF in al, 61h ; re-enable beeper
F000:06D1 and al, 0CFh
F000:06D3 out 61h, al
F000:06D5 mov al, ds:seg40.intr_flag ; get intr. flag
F000:06D8 or al, al ; will be non-zero if nmi happened
F000:06DA mov bl, 3 ; set possible error code
F000:06DC mov word ptr es:8, offset kdbnmi ; reset nmi vector
F000:06E3 pop es
F000:06E4 jz short f6_1
F000:06E6 mov al, 0 ; disable feedback ckt
F000:06E8 out 0A0h, al
F000:06EA in al, 61h
F000:06EC and al, 0FEh ; drop gate to timer 2
F000:06EE out 61h, al
F000:06F0 f6_2: ; CODE XREF: F000:06F6j
F000:06F0 in al, 62h ; see if keyboard data active
F000:06F2 and al, 40h
F000:06F4 jz short f6_x ; exit loop if data went low
F000:06F6 loop f6_2
F000:06F8 mov bl, 1
F000:06FA f6_1: ; CODE XREF: F000:06AFj
F000:06FA ; F000:06E4j
F000:06FA mov bh, 21h ; '!'
F000:06FC jmp f6
F000:06FF f6_x: ; CODE XREF: F000:f6_zj
F000:06FF ; F000:067Ej F000:0684j
F000:06FF ; F000:06F4j
F000:06FF mov al, 0 ; disable feedback ckt
F000:0701 out 0A0h, al
F000:0703 ; cassette interface test
F000:0703 call mfg_up
F000:0706 in al, 61h
F000:0708 or al, 9
F000:070A out 61h, al
F000:070C ;----- write a bit
F000:070C in al, 21h
F000:070E or al, 1 ; disable timer interrupts
F000:0710 out 21h, al
F000:0712 mov al, 10110110b ; sel tim 2, lsb, msb, md 3
F000:0712 ; (tim 2, read/load lsb/msb, square, binary)
F000:0714 out 43h, al
F000:0716 mov ax, 4D2h
F000:0719 out 42h, al
F000:071B mov al, ah
F000:071D out 42h, al
F000:071F sub cx, cx
F000:0721 l0: ; CODE XREF: F000:l0j
F000:0721 loop l0
F000:0723 ;----- read cassette input
F000:0723 in al, 62h
F000:0725 and al, 10h
F000:0727 mov ds:6Bh, al
F000:072A call read_half_bit
F000:072D call read_half_bit
F000:0730 jcxz short f8
F000:0732 push bx
F000:0733 call read_half_bit
F000:0736 pop ax
F000:0737 jcxz short f8
F000:0739 add ax, bx
F000:073B cmp ax, 0A9Ah
F000:073E jnb short f8
F000:0740 cmp ax, 8ADh
F000:0743 jb short f8
F000:0745 mov dx, 201h
F000:0748 in al, dx
F000:0749 and al, 0F0h ; determine mode
F000:074B cmp al, 10h ; mfg?
F000:074D jz short f9
F000:074F cmp al, 1000000b ; service?
F000:0751 jnz short t13_end ; go to next test if not
F000:0753 f9: ; CODE XREF: F000:074Dj
F000:0753 in al, 61h
F000:0755 mov dl, al
F000:0757 and al, 0E5h
F000:0759 out 61h, al
F000:075B xor cx, cx
F000:075D f91: ; CODE XREF: F000:f91j
F000:075D loop f91
F000:075F call read_half_bit
F000:0762 call read_half_bit
F000:0765 mov al, dl
F000:0767 out 61h, al
F000:0769 jcxz short t13_end
F000:076B mov bx, 23FFh
F000:076E jmp short f81
F000:0770 f8: ; CODE XREF: F000:0730j
F000:0770 ; F000:0737j F000:073Ej
F000:0770 ; F000:0743j
F000:0770 mov bx, 2300h
F000:0773 f81: ; CODE XREF: F000:076Ej
F000:0773 mov si, 37h ; '7'
F000:0776 call e_msg
F000:0779 t13_end: ; CODE XREF: F000:0751j
F000:0779 ; F000:0769j
F000:0779 in al, 21h
F000:077B and al, 0FEh ; enable timer ints
F000:077D out 21h, al
F000:077F in al, 0A0h ; clear nmi flip/flop
F000:0781 mov al, 10000000b ; enable nmi interrupts
F000:0783 out 0A0h, al
F000:0785 call mfg_up
F000:0788 mov dx, 2F8h
F000:078B call uart
F000:078E jnb short tm
F000:0790 mov si, 38h ; '8'
F000:0793 call e_msg
F000:0796 tm: ; CODE XREF: F000:078Ej
F000:0796 call mfg_up
F000:0799 in al, 62h
F000:079B and al, 2
F000:079D jnz short tm1
F000:079F mov dx, 3F8h
F000:07A2 call uart
F000:07A5 jnb short tm1
F000:07A7 mov si, 39h ; '9'
F000:07AA call e_msg
F000:07AD tm1: ; CODE XREF: F000:079Dj
F000:07AD ; F000:07A5j
F000:07AD sub ax, ax
F000:07AF mov es, ax
F000:07B1 mov cx, 8 ; get vector cnt
F000:07B4 push cs ; setup ds seg reg
F000:07B5 pop ds
F000:07B6 mov si, offset vector_table
F000:07B9 mov di, 20h ; ' '
F000:07BC f7a: ; CODE XREF: F000:07BFj
F000:07BC movsw
F000:07BD inc di ; skip over segment
F000:07BE inc di
F000:07BF loop f7a
F000:07C1 mov ds, cx
F000:07C3 mov word ptr ds:14h, offset print_screen ; print screen (int 0x5)
F000:07C9 mov word ptr ds:120h, offset key62_int ; 62 key conversion routine (int 0x48)
F000:07CF mov word ptr ds:110h, offset crt_char_gen ; dot table (int 0x44)
F000:07D5 mov word ptr ds:60h, offset bas_ent ; cassette basic entry (int 0x18)
F000:07DB push cs
F000:07DC pop ax
F000:07DD mov ds:62h, ax ; code segment for cassette (int 0x18)
F000:07E0 mov al, 1
F000:07E2 out 13h, al ; (activity signal)
F000:07E4 call mfg_up ; mfg routine = ee
F000:07E7 mov dx, 0C000h ; set beginning address
F000:07EA rom_scan_1: ; CODE XREF: F000:0804j
F000:07EA mov ds, dx
F000:07EC sub bx, bx
F000:07EE mov ax, [bx]
F000:07F0 push bx
F000:07F1 pop bx
F000:07F2 cmp ax, 0AA55h
F000:07F5 jnz short next_rom
F000:07F7 call rom_check
F000:07FA jmp short are_we_done
F000:07FC next_rom: ; CODE XREF: F000:07F5j
F000:07FC add dx, 80h ; '€'
F000:0800 are_we_done: ; CODE XREF: F000:07FAj
F000:0800 cmp dx, 0F000h
F000:0804 jl short rom_scan_1
F000:0806 ;----------------------------------------------------
F000:0806 ; diskette attachment test
F000:0806 ; description:
F000:0806 ; check if ipl diskette drive is attached to system. if
F000:0806 ; attached, verify status of nec fdc after a reset. issue
F000:0806 ; a recal and seek cmd to fdc and check status. complete
F000:0806 ; system initialization then pass control to the boot
F000:0806 ; loader program
F000:0806 ; mfg err codes: 2601 reset to diskette controller cd. failed
F000:0806 ; 2602 recalibrate to diskette drive failed
F000:0806 ; 2603 watchdog timer failed
F000:0806 ;----------------------------------------------------
F000:0806 call mfg_up ; mfg routine = ed
F000:0809 call dss ; point to data area
F000:080C mov al, 0FFh
F000:080E mov ds:seg40.track_0, al ; init diskette scratchpads
F000:0811 mov ds:seg40.track_1, al
F000:0814 mov ds:seg40.track_2, al
F000:0817 in al, 62h ; diskette present?
F000:0819 and al, 100b
F000:081B jz short f10_0
F000:081D jmp f15 ; no, bypass diskette test
F000:0820 f10_0: ; CODE XREF: F000:081Bj
F000:0820 or byte ptr ds:seg40.equip_flag, 1 ; set ipl diskette indication in equip. flag
F000:0825 cmp word ptr ds:seg40.reset_flag, 0 ; running from power-on state?
F000:082A jnz short f10 ; bypass watchdog test
F000:082C mov al, 0Ah ; read int. request register cmd.
F000:082E out 20h, al
F000:0830 in al, 20h
F000:0832 and al, 40h ; has watchdog gone off
F000:0834 jnz short f10 ; proceed if it has
F000:0836 mov bl, 3 ; set error code
F000:0838 jmp short f13
F000:083A f10: ; CODE XREF: F000:082Aj
F000:083A ; F000:0834j
F000:083A mov al, 80h ; '€'
F000:083C out 0F2h, al ; disable watchdog timer
F000:083E mov ah, 0 ; reset nec fdc
F000:0840 mov dl, ah ; set for drive 0
F000:0842 int 13h ; verify status after reset
F000:0844 test ah, 0FFh ; status ok?
F000:0847 mov bl, 1 ; set up possible error code
F000:0849 jnz short f13 ; no - fdc failed
F000:084B ;----- turn drive 0 motor on
F000:084B mov al, 81h ; '' ; turn motor on, drive 0
F000:084D out 0F2h, al ; write fdc control reg
F000:084F sub cx, cx
F000:0851 f11: ; CODE XREF: F000:f11j
F000:0851 loop f11 ; wait for one second
F000:0853 f12: ; CODE XREF: F000:f12j
F000:0853 loop f12
F000:0855 xor dx, dx ; select drive 0
F000:0857 mov ch, 1 ; select track 1
F000:0859 mov ds:seg40.seek_status, dl
F000:085D call seek ; recalibrate disk
F000:0860 mov bl, 2 ; error code
F000:0862 jb short f13 ; go to err subroutine if err
F000:0864 mov ch, 34 ; select track 34
F000:0866 call seek ; seek to track 34
F000:0869 jnb short f14 ; ok, turn motor off
F000:086B mov bl, 2
F000:086D f13: ; CODE XREF: F000:0838j
F000:086D ; F000:0849j F000:0862j
F000:086D mov bh, 26h ; '&' ; dsk_err: (26xx)
F000:086F mov si, offset disk_err ; get addr of msg
F000:0872 call e_msg ; go print error msg
F000:0875 f14: ; CODE XREF: F000:0869j
F000:0875 mov al, 82h ; '‚'
F000:0877 out 0F2h, al
F000:0879 in al, 0E2h
F000:087B and al, 110b
F000:087D cmp al, 10b
F000:087F jnz short f14_1
F000:0881 mov al, 84h ; '„'
F000:0883 out 0F2h, al
F000:0885 in al, 0E2h
F000:0887 and al, 110b
F000:0889 cmp al, 100b
F000:088B jnz short f14_1
F000:088D in al, 0E2h
F000:088F and al, 110000b
F000:0891 jz short f14_1
F000:0893 cmp al, 10000b
F000:0895 mov ah, 40h ; '@'
F000:0897 jz short f14_2
F000:0899 mov ah, 80h ; '€'
F000:089B f14_2: ; CODE XREF: F000:0897j
F000:089B or ds:seg40.equip_flag, ah
F000:089F ;----- turn drive 0 motor off
F000:089F f14_1: ; CODE XREF: F000:087Fj
F000:089F ; F000:088Bj F000:0891j
F000:089F mov al, 80h ; '€' ; turn drive 0 motor off
F000:08A1 out 0F2h, al
F000:08A3 f15: ; CODE XREF: F000:081Dj
F000:08A3 mov byte ptr ds:seg40.intr_flag, 0 ; set stray interrupt flag = 00
F000:08A8 mov di, 78h ; 'x' ; set default prt timeout
F000:08AB push ds
F000:08AC pop es
F000:08AD mov ax, 1414h ; default=20
F000:08B0 stosw
F000:08B1 stosw
F000:08B2 mov ax, 101h ; rs232 default=01
F000:08B5 stosw
F000:08B6 stosw
F000:08B7 in al, 21h
F000:08B9 and al, 0FEh ; enable timer int. (lvl 0)
F000:08BB out 21h, al
F000:08BD push ds
F000:08BE mov ax, 50h ; 'P'
F000:08C1 mov ds, ax
F000:08C3 cmp byte ptr ds:seg50.post_err, 0 ; check for "post_err" non-zero
F000:08C8 pop ds
F000:08C9 jz short f15a_0 ; continue if no error
F000:08CB mov dl, 2
F000:08CD call err_beep
F000:08D0 err_wait: ; CODE XREF: F000:08D7j
F000:08D0 mov ah, 0
F000:08D2 ; Return: AH = scan code, AL = character
F000:08D4 cmp ah, 1Ch
F000:08D7 jnz short err_wait
F000:08D9 jmp short f15c
F000:08DB f15a_0: ; CODE XREF: F000:08C9j
F000:08DB mov dl, 1
F000:08DD call err_beep
F000:08E0 ;----- setup printer and rs232 base addresses if device attached
F000:08E0 f15c: ; CODE XREF: F000:08D9j
F000:08E0 mov bp, offset f4
F000:08E3 xor si, si
F000:08E5 f16: ; CODE XREF: F000:08FEj
F000:08E5 mov dx, cs:[bp+0]
F000:08E9 mov al, 0AAh ; 'ª'
F000:08EB out dx, al
F000:08EC push ds
F000:08ED in al, dx
F000:08EE pop ds
F000:08EF cmp al, 0AAh ; 'ª'
F000:08F1 jnz short f17
F000:08F3 mov [si+8], dx
F000:08F7 inc si
F000:08F8 inc si
F000:08F9 f17: ; CODE XREF: F000:08F1j
F000:08F9 inc bp
F000:08FA inc bp
F000:08FB cmp bp, 41h ; 'A'
F000:08FE jnz short f16
F000:0900 xor bx, bx
F000:0902 mov dx, 3FAh
F000:0905 in al, dx
F000:0906 test al, 0F8h
F000:0908 jnz short f18
F000:090A mov word ptr [bx+0], 3F8h
F000:0910 inc bx
F000:0911 inc bx
F000:0912 f18: ; CODE XREF: F000:0908j
F000:0912 mov word ptr [bx+0], 2F8h
F000:0918 inc bx
F000:0919 inc bx
F000:091A mov ax, si
F000:091C mov cl, 3
F000:091E ror al, cl
F000:0920 or al, bl
F000:0922 or ds:11h, al
F000:0926 mov cx, ax
F000:0928 mov bx, 2FEh
F000:092B mov dx, 2FCh
F000:092E sub al, al
F000:0930 out dx, al
F000:0931 jmp short $+2
F000:0933 xchg dx, bx
F000:0935 in al, dx
F000:0936 jmp short $+2
F000:0938 mov al, 2
F000:093A xchg dx, bx
F000:093C out dx, al
F000:093D jmp short $+2
F000:093F xchg dx, bx
F000:0941 in al, dx
F000:0942 test al, 8
F000:0944 jz short f19_a
F000:0946 test al, 1
F000:0948 jnz short f19_a
F000:094A sub al, al
F000:094C xchg dx, bx
F000:094E out dx, al
F000:094F jmp short $+2
F000:0951 xchg dx, bx
F000:0953 in al, dx
F000:0954 and al, 8
F000:0956 jz short f19_a
F000:0958 ; carrier detect if following rts-indicate serial printer attached
F000:0958 or cl, 100000b
F000:095B test cl, 11000000b
F000:095E jnz short f19_a
F000:0960 or cl, 1000000b
F000:0963 mov word ptr ds:seg40.printer_base, 2F8h
F000:0969 f19_a: ; CODE XREF: F000:0944j
F000:0969 ; F000:0948j F000:0956j
F000:0969 ; F000:095Ej
F000:0969 or ds:seg40.equip_flag+1, cl
F000:096D xor dx, dx
F000:096F test cl, 40h
F000:0972 jz short f19_c
F000:0974 cmp word ptr ds:seg40, 2F8h
F000:097A jz short f19_b
F000:097C inc dx
F000:097D f19_b: ; CODE XREF: F000:097Aj
F000:097D mov ax, 87h ; '‡' ; init serial printer
F000:0980 int 14h
F000:0982 test ah, 1Eh ; error?
F000:0985 jnz short f19_c ; yes, jump
F000:0987 mov ax, 118h ; send cancel command to
F000:098A int 14h ; ...serial printer
F000:098C f19_c: ; CODE XREF: F000:0972j
F000:098C ; F000:0985j
F000:098C mov dx, 201h
F000:098F in al, dx ; get mfg./ service mode info
F000:0990 and al, 0F0h ; is high order nibble = 0 ?
F000:0992 jnz short f19_1 ; (burn-in mode)
F000:0994 f19_0: ; CODE XREF: F000:0999j
F000:0994 jmp reset
F000:0997 f19_1: ; CODE XREF: F000:0992j
F000:0997 cmp al, 100000b ; service mode loop?
F000:0999 jz short f19_0 ; branch to start
F000:099B cmp word ptr ds:seg40.reset_flag, 4321h ; diag. control program restart
F000:09A1 jz short f19_3 ; no, go boot
F000:09A3 cmp al, 10000b ; mfg dcp run request
F000:09A5 jz short f19_3
F000:09A7 mov word ptr ds:seg40.reset_flag, 1234h ; set warm start indicator in case of cartridge reset
F000:09AD int 19h ; go to boot loader
F000:09AF f19_3: ; CODE XREF: F000:09A1j
F000:09AF ; F000:09A5j
F000:09AF cli
F000:09B0 sub ax, ax
F000:09B2 mov ds, ax ; reset timer int.
F000:09B4 mov word ptr ds:20h, offset timer_int ; (int 0x08)
F000:09BA int 80h ; enter dcp through int. 80h
F000:09BC ; this subroutine is the general error handler for the post
F000:09BC ; si = offset(address) of message buffer
F000:09BC ; bx = error code for manufacturing or service mode
F000:09BC ; registers are not preserved
F000:09BC ; location "post_err" is set non-zero if an error occurs in
F000:09BC ; customer mode
F000:09BC ; service/manufacturing flags as follows: (high nibble of
F000:09BC ; port 201)
F000:09BC ; 0000 = manufacturing (burn-in) mode
F000:09BC ; 0001 = manufacturing (system test) mode
F000:09BC ; 0010 = service mode (loop post)
F000:09BC ; 0100 = service mode (system test)
F000:09BC e_msg proc near ; CODE XREF: kb_int-1477j
F000:09BC ; F000:014Ej F000:015Cj
F000:09BC ; F000:l22j F000:01BFj
F000:09BC ; F000:0295j ...
F000:09BC mov dx, 201h
F000:09BF in al, dx ; get mode bits
F000:09C0 and al, 0F0h ; isolate bits of interest
F000:09C2 jnz short em0
F000:09C4 jmp mfg_out ; manufacturing mode (burn-in)
F000:09C7 em0: ; CODE XREF: e_msg+6j
F000:09C7 cmp al, 10000b
F000:09C9 jnz short em1
F000:09CB jmp mfg_out ; mfg. mode (system test)
F000:09CE em1: ; CODE XREF: e_msg+Dj
F000:09CE mov dh, al ; save mode
F000:09D0 cmp bh, 0Ah ; error code above 0ah (crt started display possible?)
F000:09D3 jl short beeps ; do beep output if below 10
F000:09D5 push bx ; save error and mode flags
F000:09D6 push si
F000:09D7 push dx
F000:09D8 mov ah, 2 ; set cursor
F000:09DA mov dx, 1521h ; row 21, col. 33
F000:09DD mov bh, 7 ; page 7
F000:09DF ; DH,DL = row, column (0,0 = upper left)
F000:09DF ; BH = page number
F000:09E1 mov si, offset error_err ; "ERROR"
F000:09E4 mov cx, 5
F000:09E7 em_0: ; CODE XREF: e_msg+32j
F000:09E7 mov al, cs:[si]
F000:09EA inc si
F000:09EB call prt_hex
F000:09EE loop em_0
F000:09F0 ; look for a blank space to possibly put customer level errors (in
F000:09F0 ; case of multi error)
F000:09F0 mov dh, 16h
F000:09F2 em_1: ; CODE XREF: e_msg+42j
F000:09F2 mov ah, 2
F000:09F4 int 10h ; - VIDEO - SET CURSOR POSITION
F000:09F4 ; DH,DL = row, column (0,0 = upper left)
F000:09F4 ; BH = page number
F000:09F6 mov ah, 8
F000:09F8 ; BH = display page
F000:09F8 ; Return: AL = character
F000:09F8 ; AH = attribute of character (alpha modes)
F000:09FA inc dl
F000:09FC cmp al, 20h ; ' '
F000:09FE jnz short em_1
F000:0A00 pop dx
F000:0A01 pop si
F000:0A02 pop bx
F000:0A03 cmp dh, 100000b ; service mode ?
F000:0A06 jz short serv_out
F000:0A08 cmp dh, 1000000b
F000:0A0B jz short serv_out
F000:0A0D mov al, cs:[si] ; get error char
F000:0A10 call prt_hex ; display it
F000:0A13 cmp bh, 20h ; ' ' ; error below 20? (mem trouble?)
F000:0A16 jge short em_2
F000:0A18 jmp totlpt0 ; halt system if so.
F000:0A1B em_2: ; CODE XREF: e_msg+5Aj
F000:0A1B push ds
F000:0A1C push ax
F000:0A1D mov ax, 50h ; 'P'
F000:0A20 mov ds, ax
F000:0A22 mov ds:seg50.post_err, bh ; set error flag to non-zero
F000:0A26 pop ax
F000:0A27 pop ds
F000:0A28 retn ; return to caller
F000:0A29 serv_out: ; CODE XREF: e_msg+4Aj
F000:0A29 ; e_msg+4Fj
F000:0A29 mov al, bh
F000:0A2B push bx
F000:0A2C call xpc_byte
F000:0A2F pop bx
F000:0A30 mov al, bl
F000:0A32 call xpc_byte
F000:0A35 jmp totlpt0
F000:0A38 beeps: ; CODE XREF: e_msg+17j
F000:0A38 cli
F000:0A39 mov ax, cs
F000:0A3B mov ss, ax
F000:0A3D mov dl, 2
F000:0A3F mov sp, offset ex_0 ; set dummy return (eb0)
F000:0A42 eb: ; CODE XREF: e_msg+8Fj
F000:0A42 mov bl, 1
F000:0A44 jmp beep
F000:0A47 eb0: ; CODE XREF: e_msg:eb0j
F000:0A47 ; DATA XREF: F000:ex_0o
F000:0A47 ; F000:002Ao
F000:0A47 loop eb0
F000:0A49 dec dl
F000:0A4B jnz short eb
F000:0A4D cmp bh, 5
F000:0A50 jnz short totlpt0
F000:0A52 cmp dh, 20h ; ' '
F000:0A55 jz short eb1
F000:0A57 cmp dh, 40h ; '@'
F000:0A5A jnz short totlpt0
F000:0A5C eb1: ; CODE XREF: e_msg+99j
F000:0A5C mov bl, 1
F000:0A5E jmp beep
F000:0A61 mfg_out: ; CODE XREF: e_msg+8j
F000:0A61 ; e_msg+Fj
F000:0A61 ; DATA XREF: F000:01F8o
F000:0A61 cli
F000:0A62 in al, 61h
F000:0A64 and al, 0FCh
F000:0A66 out 61h, al
F000:0A68 mov dx, 11h
F000:0A6B mov al, bh ; send data to addresses 11,12
F000:0A6D out dx, al
F000:0A6E inc dx ; send high byte
F000:0A6F mov al, bl
F000:0A71 out dx, al ; send low byte
F000:0A72 ; init. on-board rs232 port for communications w/mfg monitor
F000:0A72 mov ax, 50h ; 'P'
F000:0A75 mov ds, ax ; point to data segment containing checkpoint #
F000:0A77 mov ax, cs
F000:0A79 mov ss, ax ; set stack for rtn
F000:0A7B mov sp, offset ex1 ; (points to mo1)
F000:0A7E mov dx, 2FBh ; line control reg. address
F000:0A81 jmp s8250 ; go set up for 9600, 0dd, 2 stop bits, 8 bits
F000:0A84 mo1: ; DATA XREF: F000:ex1o
F000:0A84 mov cx, dx ; dx came back with xmit reg address in it
F000:0A86 mov dx, 2FCh ; modem control reg
F000:0A89 sub al, al ; set dtr and rts low so possible wrap plug won't confuse things
F000:0A8B out dx, al
F000:0A8C mov dx, 2FEh ; modem status reg
F000:0A8F mo2: ; CODE XREF: e_msg+D6j
F000:0A8F in al, dx
F000:0A90 and al, 10000b ; cts up yet?
F000:0A92 jz short mo2 ; loop til it is
F000:0A94 dec dx ; set dx=2fd (line status reg)
F000:0A95 xchg dx, cx ; point to xmit. data reg
F000:0A97 mov al, ds:seg50.mfg_tst ; get mfg routine error indicator
F000:0A9A out dx, al ; (maybe wrong from early errors)
F000:0A9B jmp short $+2 ; delay
F000:0A9D xchg dx, cx ; point dx=2fd
F000:0A9F mo3: ; CODE XREF: e_msg+E8j
F000:0A9F in al, dx ; transmit empty?
F000:0AA0 and al, 100000b
F000:0AA2 jmp short $+2 ; delay
F000:0AA4 jz short mo3 ; loop til it is
F000:0AA6 xchg dx, cx
F000:0AA8 mov al, bh ; get msb of error word
F000:0AAA out dx, al
F000:0AAB jmp short $+2 ; delay
F000:0AAD xchg dx, cx
F000:0AAF mo4: ; CODE XREF: e_msg+F8j
F000:0AAF in al, dx ; wait for xmit empty
F000:0AB0 and al, 100000b
F000:0AB2 jmp short $+2 ; delay
F000:0AB4 jz short mo4
F000:0AB6 mov al, bl ; get lsb of error word
F000:0AB8 xchg dx, cx
F000:0ABA out dx, al
F000:0ABB totlpt0: ; CODE XREF: e_msg+5Cj
F000:0ABB ; e_msg+79j e_msg+94j
F000:0ABB ; e_msg+9Ej
F000:0ABB ; DATA XREF: F000:002Co
F000:0ABB cli ; disable ints.
F000:0ABC sub al, al
F000:0ABE out 0F2h, al ; stop diskette motor
F000:0AC0 out 0A0h, al ; disable nmi
F000:0AC2 hlt ; halt
F000:0AC3 retn
F000:0AC3 e_msg endp
F000:0AC4 i8250 proc near ; CODE XREF: uart+Dp
F000:0AC4 ; uart+11Ep
F000:0AC4 in al, dx
F000:0AC5 mov bl, 2
F000:0AC7 call rr2
F000:0ACA and al, 0F0h
F000:0ACC jnz short at20
F000:0ACE call rr1
F000:0AD1 and al, 0F8h
F000:0AD3 jnz short at20
F000:0AD5 inc dx
F000:0AD6 call rr1
F000:0AD9 and al, 0E0h
F000:0ADB jnz short at20
F000:0ADD call rr1
F000:0AE0 and al, 80h
F000:0AE2 jnz short at20
F000:0AE4 mov al, 60h ; '`'
F000:0AE6 out dx, al
F000:0AE7 jmp short $+2
F000:0AE9 inc dx
F000:0AEA xor al, al
F000:0AEC out dx, al
F000:0AED call rr3
F000:0AF0 sub dx, 6
F000:0AF3 in al, dx
F000:0AF4 clc
F000:0AF5 retn
F000:0AF6 at20: ; CODE XREF: i8250+8j
F000:0AF6 ; i8250+Fj i8250+17j
F000:0AF6 ; i8250+1Ej
F000:0AF6 stc
F000:0AF7 retn
F000:0AF7 i8250 endp
F000:0AF8 ict proc near ; CODE XREF: uart+36p
F000:0AF8 ; uart+90p uart+D1p
F000:0AF8 in al, dx
F000:0AF9 jmp short $+2
F000:0AFB or al, ah
F000:0AFD out dx, al
F000:0AFE sub dx, cx
F000:0B00 push cx
F000:0B01 sub cx, cx
F000:0B03 at21: ; CODE XREF: ict+10j
F000:0B03 in al, dx
F000:0B04 test al, 1
F000:0B06 jz short at22
F000:0B08 loop at21
F000:0B0A at22: ; CODE XREF: ict+Ej
F000:0B0A pop cx
F000:0B0B cmp al, bh
F000:0B0D jnz short at23
F000:0B0F or bl, bl
F000:0B11 jz short at24
F000:0B13 add dx, cx
F000:0B15 in al, dx
F000:0B16 jmp short at24
F000:0B18 at23: ; CODE XREF: ict+15j
F000:0B18 mov al, 0FFh
F000:0B1A at24: ; CODE XREF: ict+19j ict+1Ej
F000:0B1A retn
F000:0B1A ict endp
F000:0B1B ; --- int 0x19 -------------------------------
F000:0B1B ; boot strap loader
F000:0B1B ;
F000:0B1B ; track 0, sector 1 is read into the
F000:0B1B ; boot location (segment 0, offset 7c00)
F000:0B1B ; and control is transferred there
F000:0B1B ;
F000:0B1B ; if the diskette is not present or has a
F000:0B1B ; problem loading (e.g., not ready), and int.
F000:0B1B ; 18h is executed. if a cartridge has vectored
F000:0B1B ; int 18h to itself, control will be passed to
F000:0B1B ; the cartridge.
F000:0B1B ; --------------------------------------------
F000:0B1B boot_strap proc near ; CODE XREF: F000:E6F2j
F000:0B1B ; DATA XREF: F000:FF15o
F000:0B1B sti ; enable interrupts
F000:0B1C sub ax, ax ; set 40x25 b&w mode on crt
F000:0B1E int 10h
F000:0B20 sub ax, ax ; establish addressing
F000:0B22 mov ds, ax
F000:0B24 ;----- see if diskette is present
F000:0B24 in al, 62h ; get config bits
F000:0B26 and al, 100b ; is diskette present?
F000:0B28 jnz short h3 ; no, then attempt to go to cart
F000:0B2A ;----- reset the disk parameter table vector
F000:0B2A mov word ptr ds:78h, offset disk_parms ; (int 0x1e offset)
F000:0B30 mov word ptr ds:7Ah, cs ; (int 0x1e segment)
F000:0B34 ;----- load system from diskette -- cx has retry count
F000:0B34 mov cx, 4 ; set retry count
F000:0B37 h1: ; CODE XREF: boot_strap+35j
F000:0B37 push cx ; save retry count
F000:0B38 mov ah, 0 ; reset the diskette system
F000:0B3A int 13h ; diskette_io
F000:0B3C jb short h2 ; if error, try again
F000:0B3E mov ax, 201h ; read in the single sector
F000:0B41 sub dx, dx ; to the boot location
F000:0B43 mov es, dx
F000:0B45 mov bx, 7C00h ; (boot location)
F000:0B48 mov cx, 1 ; drive 0, head 0, sector 1, track 0
F000:0B4B int 13h ; diskette_io
F000:0B4D h2: ; CODE XREF: boot_strap+21j
F000:0B4D pop cx ; recover retry count
F000:0B4E jnb short h3a ; cf set by unsuccessful read
F000:0B50 loop h1 ; do it for retry times
F000:0B52 ;----- unable to ips from diskette
F000:0B52 h3: ; CODE XREF: boot_strap+Dj
F000:0B52 int 18h ; go to basic or cartridge
F000:0B54 ;----- ips was successful
F000:0B54 h3a: ; CODE XREF: boot_strap+33j
F000:0B54 jmp far ptr 0:7C00h ; (boot location)
F000:0B54 boot_strap endp
F000:0B59 podstg proc near ; CODE XREF: F000:016Aj
F000:0B59 ; F000:0183j F000:01B7j
F000:0B59 ; F000:0552p F000:0584p
F000:0B59 ; F000:05A9p
F000:0B59 cld
F000:0B5A sub di, di
F000:0B5C sub ax, ax
F000:0B5E mov ds, ax
F000:0B60 mov bx, ds:472h ; (0:472 == 40:72 == reset flag)
F000:0B64 cmp bx, 1234h
F000:0B68 mov dx, es
F000:0B6A mov ds, dx
F000:0B6C jnz short p1
F000:0B6E p12: ; CODE XREF: podstg+24j
F000:0B6E rep stosw ; simple fill with 0 on warm-start
F000:0B70 mov ds, ax
F000:0B72 mov ds:472h, bx ; (0:472 == 40:72 == reset flag)
F000:0B76 mov ds, dx
F000:0B78 retn
F000:0B79 p1: ; CODE XREF: podstg+13j
F000:0B79 cmp bx, 4321h ; diag. restart?
F000:0B7D jz short p12 ; do fill with zeroes
F000:0B7F p2: ; CODE XREF: podstg+35j
F000:0B7F mov [di], al
F000:0B81 mov al, [di]
F000:0B83 xor al, ah
F000:0B85 jz short py
F000:0B87 jmp p8
F000:0B8A py: ; CODE XREF: podstg+2Cj
F000:0B8A inc ah
F000:0B8C mov al, ah
F000:0B8E jnz short p2
F000:0B90 mov bp, cx
F000:0B92 mov ax, 0AAAAh
F000:0B95 mov bx, ax
F000:0B97 mov dx, 5555h
F000:0B9A rep stosw
F000:0B9C dec di
F000:0B9D dec di
F000:0B9E std
F000:0B9F mov si, di
F000:0BA1 mov cx, bp
F000:0BA3 p3: ; CODE XREF: podstg+52j
F000:0BA3 lodsw
F000:0BA4 xor ax, bx
F000:0BA6 jnz short p8
F000:0BA8 mov ax, dx
F000:0BAA stosw
F000:0BAB loop p3
F000:0BAD mov cx, bp
F000:0BAF cld
F000:0BB0 inc si
F000:0BB1 inc si
F000:0BB2 mov di, si
F000:0BB4 mov bx, dx
F000:0BB6 mov dx, 0FFh
F000:0BB9 px: ; CODE XREF: podstg+68j
F000:0BB9 ; podstg+77j
F000:0BB9 lodsw
F000:0BBA xor ax, bx
F000:0BBC jnz short p8
F000:0BBE mov ax, dx
F000:0BC0 stosw
F000:0BC1 loop px
F000:0BC3 mov cx, bp
F000:0BC5 std
F000:0BC6 dec si
F000:0BC7 dec si
F000:0BC8 mov di, si
F000:0BCA mov bx, dx
F000:0BCC not dx
F000:0BCE or dl, dl
F000:0BD0 jz short px
F000:0BD2 cld
F000:0BD3 add si, 4
F000:0BD6 not dx
F000:0BD8 mov di, si
F000:0BDA mov cx, bp
F000:0BDC p4: ; CODE XREF: podstg+89j
F000:0BDC lodsw
F000:0BDD xor ax, dx
F000:0BDF jnz short p8
F000:0BE1 stosw
F000:0BE2 loop p4
F000:0BE4 std
F000:0BE5 dec si
F000:0BE6 dec si
F000:0BE7 ;----- check if in service/mfg modes, if so, perform refresh check
F000:0BE7 mov dx, 201h
F000:0BEA in al, dx ; get options bits
F000:0BEB and al, 0F0h
F000:0BED cmp al, 0F0h ; 'ð' ; all bits high=normal mode (no joy buttons pressed)
F000:0BEF jz short p6
F000:0BF1 mov cx, cs
F000:0BF3 mov bx, ss
F000:0BF5 cmp cx, bx
F000:0BF7 jz short p6
F000:0BF9 mov al, 18h
F000:0BFB p5: ; CODE XREF: podstg:p5j
F000:0BFB ; podstg+A6j
F000:0BFB loop p5
F000:0BFD dec al
F000:0BFF jnz short p5
F000:0C01 p6: ; CODE XREF: podstg+96j
F000:0C01 ; podstg+9Ej
F000:0C01 mov cx, bp
F000:0C03 p7: ; CODE XREF: podstg+AFj
F000:0C03 lodsw
F000:0C04 or ax, ax
F000:0C06 jnz short p8
F000:0C08 loop p7
F000:0C0A jmp short p11
F000:0C0C p8: ; CODE XREF: podstg+2Ej
F000:0C0C ; podstg+4Dj podstg+63j
F000:0C0C ; podstg+86j podstg+ADj
F000:0C0C mov cx, ax
F000:0C0E xor ah, ah
F000:0C10 or ch, ch
F000:0C12 jz short p9
F000:0C14 inc ah
F000:0C16 p9: ; CODE XREF: podstg+B9j
F000:0C16 or cl, cl
F000:0C18 jz short p10
F000:0C1A add ah, 2
F000:0C1D p10: ; CODE XREF: podstg+BFj
F000:0C1D or ah, ah
F000:0C1F p11: ; CODE XREF: podstg+B1j
F000:0C1F cld
F000:0C20 retn
F000:0C20 podstg endp
F000:0C21 put_logo proc near ; CODE XREF: F000:04BDp
F000:0C21 push ds
F000:0C22 push bp
F000:0C23 push ax
F000:0C24 push bx
F000:0C25 push cx
F000:0C26 push dx
F000:0C27 mov bp, offset logo
F000:0C2A mov dx, 8000h ; point dh dl at row column 0, 0
F000:0C2D mov bl, 11111b ; attribute of characters to be written
F000:0C2F int 82h ; call output routine
F000:0C31 mov bl, 0 ; initialize attribute
F000:0C33 mov dl, 0 ; initialize column
F000:0C35 again: ; CODE XREF: put_logo+20j
F000:0C35 mov dh, 94h ; '”' ; set line
F000:0C37 mov bp, offset color ; output given color bar
F000:0C3A int 82h ; call output routine
F000:0C3C inc bl ; increment attribute
F000:0C3E cmp dl, 32 ; is the column counter pointing past 40?
F000:0C41 jl short again ; if not, do it again
F000:0C43 pop dx
F000:0C44 pop cx
F000:0C45 pop bx
F000:0C46 pop ax
F000:0C47 pop bp ; restore bp
F000:0C48 pop ds ; restore ds
F000:0C49 retn
F000:0C49 put_logo endp
F000:0C4A logo db 3 ; DATA XREF: put_logo+6o
F000:0C4B db 20h ; space
F000:0C4C db 0DCh ; half block
F000:0C4D logo_e db 28h, 0FBh, 28h, 0FBh, 2, 7, 1, 9, 3, 4, 9, 4, 1, 0FBh
F000:0C4D db 2, 7, 1, 0Ah, 2, 5, 7, 5, 1, 0FBh, 2, 7, 1, 0Bh, 1
F000:0C4D db 6, 5, 6, 1, 0FBh, 4, 3, 5, 4 dup(3), 5, 3, 5, 3, 0FBh
F000:0C4D db 4, 3, 5, 4 dup(3), 6, 1, 6, 3, 0FBh, 4, 3, 5, 8, 4
F000:0C4D db 0Dh, 3, 0FBh, 4, 3, 5, 7, 5, 0Dh, 3, 0FBh, 4, 3, 5
F000:0C4D db 8, 4, 0Dh, 3, 0FBh, 4, 3, 5, 4 dup(3), 0Dh, 3, 0FBh
F000:0C4D db 4, 3, 5, 5 dup(3), 1, 5, 1, 2 dup(3), 0FBh, 2, 7, 1
F000:0C4D db 0Bh, 1, 5, 2, 3, 2, 5, 1, 0FBh, 2, 7, 1, 0Ah, 2, 5
F000:0C4D db 3, 1, 3, 5, 1, 0FBh, 2, 7, 1, 9, 3, 5, 7, 5, 1, 0FBh
F000:0C4D db 28h, 0FBh, 28h, 0FCh
F000:0CDD color db 2 ; DATA XREF: put_logo+16o
F000:0CDE db 0DBh ; Û ; full block
F000:0CDF color_e db 2, 77h, 2, 77h, 2, 77h, 2, 77h, 2, 0FCh
F000:0CE9 moo10 dw offset set_mode ; DATA XREF: video_io+38r
F000:0CE9 ; 0x00
F000:0CEB dw offset set_ctype ; 0x01
F000:0CED dw offset set_cpos ; 0x02
F000:0CEF dw offset read_cursor ; 0x03
F000:0CF1 dw offset read_lpen ; 0x04
F000:0CF3 dw offset act_disp_page ; 0x05
F000:0CF5 dw offset scroll_up ; 0x06
F000:0CF7 dw offset scroll_down ; 0x07
F000:0CF9 dw offset read_ac_current ; 0x08
F000:0CFB dw offset write_ac_current ; 0x09
F000:0CFD dw offset write_c_current ; 0x0a
F000:0CFF dw offset set_color ; 0x0b
F000:0D01 dw offset write_dot ; 0x0c
F000:0D03 dw offset read_dot ; 0x0d
F000:0D05 dw offset write_tty ; 0x0e
F000:0D07 dw offset video_state ; 0x0f
F000:0D09 dw offset set_palette ; 0x10
F000:0D0B video_io proc far ; CODE XREF: F000:F065j
F000:0D0B ; DATA XREF: F000:vector_table_16o
F000:0D0B sti ; interrupts back on
F000:0D0C cld
F000:0D0D push es
F000:0D0E push ds ; save segment registers
F000:0D0F push dx
F000:0D10 push cx
F000:0D11 push bx
F000:0D12 push si
F000:0D13 push di
F000:0D14 push ax ; save ax value
F000:0D15 mov al, ah ; get into low byte
F000:0D17 xor ah, ah ; zero to high byte
F000:0D19 shl ax, 1 ; #2 for table lookup
F000:0D1B mov si, ax ; put into si for branch
F000:0D1D cmp ax, 22h ; '"' ; test for within range
F000:0D20 jb short c1
F000:0D22 pop ax ; throw away the parameters
F000:0D23 jmp video_return ; do nothing if not in range
F000:0D26 c1: ; CODE XREF: video_io+15j
F000:0D26 call dss
F000:0D29 mov ax, 0B800h ; segment for color card
F000:0D2C cmp byte ptr ds:seg40.crt_mode, 9 ; in mode using 32k regen?
F000:0D31 jb short c2 ; no, jump
F000:0D33 mov ah, ds:seg40.pagdat ; get copy of page regs
F000:0D37 and ah, 111000b ; isolate cpu reg
F000:0D3A shr ah, 1 ; shift to make it into segment value
F000:0D3C c2: ; CODE XREF: video_io+26j
F000:0D3C mov es, ax ; set up to point at video ram area
F000:0D3E pop ax ; recover value
F000:0D3F mov ah, ds:seg40.crt_mode ; get current mode into ah
F000:0D43 jmp cs:moo10[si]
F000:0D43 video_io endp
F000:0D48 ; table of regen lenghts
F000:0D48 moo50 dw 2048 ; DATA XREF: set_mode+1B6r
F000:0D48 ; mode 0 40x25 bw
F000:0D4A dw 2048 ; mode 1 40x25 color
F000:0D4C dw 4096 ; mode 2 80x25 bw
F000:0D4E dw 4096 ; mode 3 80x25 color
F000:0D50 dw 16384 ; mode 4 320x200 4 color
F000:0D52 dw 16384 ; mode 5 320x200 4 color
F000:0D54 dw 16384 ; mode 6 640x200 bw
F000:0D56 dw 0
F000:0D58 dw 16384 ; mode 8 160x200 16 color
F000:0D5A dw 32768 ; mode 9 320x200 16 color
F000:0D5C dw 32768 ; mode a 640x200 4 color
F000:0D5E ;------ columns
F000:0D5E moo60 db 40, 40, 80, 80, 40, 40, 80, 0, 20, 40, 80
F000:0D5E ; DATA XREF: set_mode+1AAr
F000:0D5E ; columns
F000:0D69 ;------ table of gate array parameters for mode settings (0x03da)
F000:0D69 ;model control1, palette mask, border color, mode control 2
F000:0D69 moo70 db 0Ch, 0Fh, 0, 2 ; DATA XREF: set_mode+9Do
F000:0D69 ; mode 0 40x25 bw
F000:0D6D moo70l db 8, 0Fh, 0, 2 ; mode 1 40x25 color
F000:0D71 db 0Dh, 0Fh, 0, 2 ; mode 2 80x25 bw
F000:0D75 db 9, 0Fh, 0, 2 ; mode 3 80x25 color
F000:0D79 db 0Ah, 3, 0, 0 ; mode 4 320x200 4 color
F000:0D7D db 0Eh, 3, 0, 0 ; mode 5 320x200 bw
F000:0D81 db 0Eh, 1, 0, 8 ; mode 6 640x200 bw
F000:0D85 db 0, 0, 0, 0 ; mode 7 invalid
F000:0D89 db 1Ah, 0Fh, 0, 0 ; mode 8 160x200 16 color
F000:0D8D db 1Bh, 0Fh, 0, 0 ; mode 9 320x200 16 color
F000:0D91 db 0Bh, 3, 0, 0 ; mode a 640x200 4 color
F000:0D95 ;---------- tables of palette colors for 2 and 4 color modes
F000:0D95 moo72 db 0, 0Fh, 0, 0 ; DATA XREF: set_mode+42o
F000:0D95 ; set_color+28o
F000:0D95 ; 2 color, set 0
F000:0D99 moo72l db 0Fh, 0, 0, 0 ; 2 color, set 1
F000:0D9D moo74 db 0, 2, 4, 6 ; DATA XREF: set_color:c32o
F000:0D9D ; 4 color, set 0
F000:0DA1 moo75 db 0, 3, 5, 0Fh ; DATA XREF: set_mode+49o
F000:0DA1 ; 4 color, set 1
F000:0DA5 set_mode proc far ; CODE XREF: video_io+38j
F000:0DA5 ; DATA XREF: F000:moo10o
F000:0DA5 push ax ; save input mode on stack
F000:0DA6 and al, 7Fh ; remove clear regen switch
F000:0DA8 cmp al, 7 ; check for valid modes
F000:0DAA jz short c3 ; mode 7 is invalid
F000:0DAC cmp al, 0Bh
F000:0DAE jb short c4 ; greater than 0xa is invalid
F000:0DB0 c3: ; CODE XREF: set_mode+5j
F000:0DB0 mov al, 0 ; default to mode 0
F000:0DB2 c4: ; CODE XREF: set_mode+9j
F000:0DB2 cmp al, 2 ; check for modes needing 128k
F000:0DB4 jz short c5
F000:0DB6 cmp al, 3
F000:0DB8 jz short c5
F000:0DBA cmp al, 9
F000:0DBC jb short c6
F000:0DBE c5: ; CODE XREF: set_mode+Fj
F000:0DBE ; set_mode+13j
F000:0DBE cmp word ptr ds:seg40.true_mem, 128 ; do we have 128k?
F000:0DC4 jnb short c6 ; yes, jump
F000:0DC6 mov al, 0 ; no, default to mode 0
F000:0DC8 c6: ; CODE XREF: set_mode+17j
F000:0DC8 ; set_mode+1Fj
F000:0DC8 mov dx, 3D4h ; address of color card
F000:0DCB mov ah, al ; save mode in ah
F000:0DCD mov ds:seg40.crt_mode, al ; save in global variable
F000:0DD0 mov ds:seg40.addr_6845, dx ; save address in base
F000:0DD4 mov di, ax ; save mode in di
F000:0DD6 mov dx, 3DAh ; point to control register
F000:0DD9 in al, dx ; sync control reg to address
F000:0DDA xor al, al ; set vga reg 0 (mode control 1)
F000:0DDC out dx, al ; select it
F000:0DDD mov al, ds:seg40.crt_mode_set ; get last mode set
F000:0DE0 and al, 11110111b ; turn off video
F000:0DE2 out dx, al ; set in gate array
F000:0DE3 ; ----- set default palettes
F000:0DE3 mov ax, di ; get mode
F000:0DE5 mov ah, 10h ; set palette reg 0
F000:0DE7 mov bx, offset moo72 ; point to table entry
F000:0DEA cmp al, 6 ; 2 color mode?
F000:0DEC jz short c7 ; yes, jump
F000:0DEE mov bx, offset moo75 ; point to table entry
F000:0DF1 cmp al, 5 ; check for 4 color mode
F000:0DF3 jz short c7 ; yes, jump
F000:0DF5 cmp al, 4 ; check for 4 color mode
F000:0DF7 jz short c7 ; yes, jump
F000:0DF9 cmp al, 0Ah ; check for 4 color mode
F000:0DFB jnz short c9 ; no, jump
F000:0DFD c7: ; CODE XREF: set_mode+47j
F000:0DFD ; set_mode+4Ej set_mode+52j
F000:0DFD mov cx, 4 ; number of regs to set
F000:0E00 c8: ; CODE XREF: set_mode+65j
F000:0E00 mov al, ah ; get reg number
F000:0E02 out dx, al ; select it
F000:0E03 mov al, cs:[bx] ; get data
F000:0E06 out dx, al ; set it
F000:0E07 inc ah ; next reg
F000:0E09 inc bx ; next table value
F000:0E0A loop c8
F000:0E0C jmp short c11
F000:0E0E ;----- set palettes for 16 color
F000:0E0E c9: ; CODE XREF: set_mode+56j
F000:0E0E mov cx, 10h ; number of palettes, ah is reg counter
F000:0E11 c10: ; CODE XREF: set_mode+72j
F000:0E11 mov al, ah ; get reg number
F000:0E13 out dx, al ; select it
F000:0E14 out dx, al ; set palette value
F000:0E15 inc ah ; next reg
F000:0E17 loop c10
F000:0E19 ;----- setup m0 & m1 in pagreg
F000:0E19 c11: ; CODE XREF: set_mode+67j
F000:0E19 mov ax, di ; get current mode
F000:0E1B xor bl, bl ; set up for alpha mode
F000:0E1D cmp al, 4 ; in alpha mode?
F000:0E1F jb short c12 ; yes, jump
F000:0E21 mov bl, 1000000b ; set up for 16k regen (bit 6 on)
F000:0E23 cmp al, 9 ; mode use 16k
F000:0E25 jb short c12 ; yes, jump
F000:0E27 mov bl, 11000000b ; set up for 32k regen (bit 7,6 on)
F000:0E29 c12: ; CODE XREF: set_mode+7Aj
F000:0E29 ; set_mode+80j
F000:0E29 mov dx, 3DFh ; set port address of pagreg
F000:0E2C mov al, ds:seg40.pagdat ; get last data output
F000:0E2F and al, 3Fh ; '?' ; clear m0 & m1 bits
F000:0E31 or al, bl ; set new bits
F000:0E33 out dx, al ; stuff back in port (update video address mode)
F000:0E34 mov ds:seg40.pagdat, al ; save copy in ram
F000:0E37 ;----- enable video and correct port settings
F000:0E37 mov ax, di ; get current mode
F000:0E39 xor ah, ah ; into ax reg
F000:0E3B mov cx, 4 ; set table entry lenght (moo70l)
F000:0E3E mul cx ; times mode for offset into table
F000:0E40 mov bx, ax ; table offset in bx
F000:0E42 add bx, offset moo70 ; add table start to offset
F000:0E46 mov ah, cs:[bx] ; save mode set and palette (ah=mode control 1)
F000:0E49 mov al, cs:[bx+2] ; till we can put them in ram (al=border color)
F000:0E4D mov si, ax
F000:0E4F cli ; disable interrupts
F000:0E50 call mode_alive ; keep memory data valid
F000:0E53 mov al, 10000b ; disable nmi and hold request
F000:0E55 out 0A0h, al
F000:0E57 mov dx, 3DAh
F000:0E5A mov al, 4 ; point to reset reg
F000:0E5C out dx, al ; send to gate array
F000:0E5D mov al, 2 ; set synchronous reset
F000:0E5F out dx, al ; do it
F000:0E60 ; while the gate array is in reset state, we cannot access ram
F000:0E60 mov ax, si ; restore new mode set (ah=mode control 1, al=border color)
F000:0E62 and ah, 11110111b ; turn off video enable (bit 3: video enable)
F000:0E65 xor al, al ; set up to select vga reg 0 (mode control 1)
F000:0E67 out dx, al ; select it
F000:0E68 xchg ah, al ; ah is vga reg counter
F000:0E6A out dx, al ; set mode
F000:0E6B mov al, 4 ; set up to select vga reg 4 (reset)
F000:0E6D out dx, al ; select it
F000:0E6E xor al, al ; (low before changing modes)
F000:0E70 out dx, al ; remove reset from vga
F000:0E71 ; now ok to access ram again
F000:0E71 mov al, 80h ; '€' ; enable nmi again
F000:0E73 out 0A0h, al ; 0xa0 = nmi_port
F000:0E75 call mode_alive ; keep memory data valid
F000:0E78 sti
F000:0E79 jmp short c14
F000:0E7B c13: ; CODE XREF: set_mode+E0j
F000:0E7B mov al, ah ; get vga reg number
F000:0E7D out dx, al ; select reg
F000:0E7E mov al, cs:[bx] ; get table value
F000:0E81 out dx, al ; put in vga reg
F000:0E82 c14: ; CODE XREF: set_mode+D4j
F000:0E82 inc bx ; next in table
F000:0E83 inc ah ; next reg
F000:0E85 loop c13 ; do entire entry
F000:0E87 ;---- set up crt and cpu page regs according to mode & memory size
F000:0E87 mov dx, 3DFh ; set io address of pagreg
F000:0E8A mov al, ds:seg40.pagdat ; get last data output
F000:0E8D and al, 11000000b ; clear reg bits
F000:0E8F mov bl, 110110b ; set up for graphics mode with 32k regen
F000:0E91 test al, 80h ; '€' ; in this mode?
F000:0E93 jnz short c15 ; yes, jump
F000:0E95 mov bl, 111111b ; set up for 16k regen and 128k memory
F000:0E97 cmp word ptr ds:seg40.true_mem, 128 ; do we have 128k?
F000:0E9D jnb short c15 ; yes, jump
F000:0E9F mov bl, 11011b ; set up for 16k regen and 64k memory
F000:0EA1 c15: ; CODE XREF: set_mode+EEj
F000:0EA1 ; set_mode+F8j
F000:0EA1 or al, bl ; combine mode bits and reg values
F000:0EA3 out dx, al ; set port
F000:0EA4 mov ds:seg40.pagdat, al ; save copy in ram
F000:0EA7 mov ax, si ; put mode set & palette in ram
F000:0EA9 mov ds:seg40.crt_mode_set, ah
F000:0EAD mov ds:seg40.crt_palette, al
F000:0EB0 in al, 61h ; get current value of 8255 port b
F000:0EB2 and al, 11111011b ; set up graphics mode
F000:0EB4 test ah, 2 ; just set alpha mode in vga?
F000:0EB7 jnz short c16 ; yes, jump
F000:0EB9 or al, 4 ; set up alpha mode
F000:0EBB c16: ; CODE XREF: set_mode+112j
F000:0EBB out 61h, al ; stuff back in 8255
F000:0EBD ;----- set up 6845
F000:0EBD push ds ; save data segment value
F000:0EBE xor ax, ax ; set up for abs0 segment
F000:0EC0 mov ds, ax ; establish vector table addressing
F000:0EC2 lds bx, ds:74h ; get pointer to video parms (int 0x1d)
F000:0EC6 mov ax, di ; get current mode in ax
F000:0EC8 mov cx, 10h ; lenghts of each row of table
F000:0ECB nop
F000:0ECC cmp ah, 2 ; determine which to use
F000:0ECF jb short c17 ; mode is 0 or 1
F000:0ED1 add bx, cx ; move to next row of init table
F000:0ED3 cmp ah, 4
F000:0ED6 jb short c17 ; mode is 2 or 3
F000:0ED8 add bx, cx ; move to graphics row of
F000:0EDA cmp ah, 9 ; init_table
F000:0EDD jb short c17 ; mode is 4, 5, 6, 8 or 9
F000:0EDF add bx, cx ; move to next graphics row of init_table
F000:0EE1 ;----- bx points to correct row of initialization table
F000:0EE1 c17: ; CODE XREF: set_mode+12Aj
F000:0EE1 ; set_mode+131j
F000:0EE1 ; set_mode+138j
F000:0EE1 push ax ; save mode in ah
F000:0EE2 mov al, [bx+2] ; get horz. sync position
F000:0EE5 mov di, [bx+0Ah] ; get cursor type
F000:0EE8 push ds
F000:0EE9 call dss
F000:0EEC mov ds:seg40.horz_pos, al ; save horz. sync position variable
F000:0EEF mov ds:seg40.cursor_mode, di ; save cursor mode
F000:0EF3 push ax
F000:0EF4 mov al, ds:seg40.var_delay ; set default offset
F000:0EF7 and al, 0Fh
F000:0EF9 mov ds:seg40.var_delay, al
F000:0EFC pop ax
F000:0EFD pop ds
F000:0EFE xor ah, ah ; ah will serve as register number during loop
F000:0F00 mov dx, 3D4h ; point to 6845
F000:0F03 ; loop through table, outputting reg address, then value from table
F000:0F03 c18: ; CODE XREF: set_mode+169j
F000:0F03 mov al, ah ; get 6845 register number
F000:0F05 out dx, al
F000:0F06 inc dx ; point to data port
F000:0F07 inc ah ; next register value
F000:0F09 mov al, [bx] ; get table value
F000:0F0B out dx, al ; out to chip
F000:0F0C inc bx ; next in table
F000:0F0D dec dx ; back to pointer register
F000:0F0E loop c18 ; do the whole table
F000:0F10 pop ax ; get mode back
F000:0F11 pop ds ; recover segment value
F000:0F12 ;----- fill regen area with blank
F000:0F12 xor di, di ; set up pointer for regen
F000:0F14 mov ds:seg40.crt_start, di ; start address saved in global
F000:0F18 mov byte ptr ds:seg40.active_page, 0 ; set page value
F000:0F1D pop dx ; get original input back
F000:0F1E and dl, 80h ; no clear of regen?
F000:0F21 jnz short c21 ; skip clearing regen
F000:0F23 mov dx, 0B800h ; setup segment for 16k regen area
F000:0F26 mov cx, 8192 ; number of words to clear (16k)
F000:0F29 cmp al, 9 ; require 32k byte regen?
F000:0F2B jb short c19 ; no, jump
F000:0F2D shl cx, 1 ; set 16k words to clear (32k)
F000:0F2F mov dx, 1800h ; set up segment for 32k regen arean
F000:0F32 c19: ; CODE XREF: set_mode+186j
F000:0F32 mov es, dx ; set regen segment
F000:0F34 cmp al, 4 ; test for graphics
F000:0F36 mov ax, 0F20h ; fill char for alpha (' ' + 15*256)
F000:0F39 jb short c20 ; no_graphics_init
F000:0F3B xor ax, ax ; fill for graphics mode
F000:0F3D c20: ; CODE XREF: set_mode+194j
F000:0F3D rep stosw ; fill the regen area with blanks
F000:0F3F ;----- enable video
F000:0F3F c21: ; CODE XREF: set_mode+17Cj
F000:0F3F mov dx, 3DAh ; set port address of vga
F000:0F42 xor al, al ; (al=0 -> mode control 1)
F000:0F44 out dx, al ; select vga reg 0
F000:0F45 mov al, ds:seg40.crt_mode_set ; get mode set value
F000:0F48 out dx, al ; set mode
F000:0F49 ;----- determine number of columns, both for entire display
F000:0F49 ;----- and the number to be used for tty interface
F000:0F49 xor bh, bh
F000:0F4B mov bl, ds:seg40.crt_mode
F000:0F4F mov al, cs:moo60[bx]
F000:0F54 xor ah, ah
F000:0F56 mov ds:seg40.crt_cols, ax ; number of columns in this screen
F000:0F59 ;----- set cursor positions
F000:0F59 shl bx, 1 ; word offset into clear length table
F000:0F5B mov cx, cs:moo50[bx] ; length to clear
F000:0F60 mov ds:seg40.crt_len, cx ; save length of crt
F000:0F64 mov cx, 8 ; clear all cursor positions
F000:0F67 mov di, seg40.cursor_posn
F000:0F6A push ds ; establish segment
F000:0F6B pop es ; addressing
F000:0F6C xor ax, ax ; fill with zeroes
F000:0F6E rep stosw
F000:0F70 video_return: ; CODE XREF: video_io+18j
F000:0F70 ; write_tty+5Ej
F000:0F70 ; set_ctype+11j
F000:0F70 ; set_cpos:loc_FE49Fj
F000:0F70 ; act_disp_page+25j
F000:0F70 ; set_color+22j ...
F000:0F70 pop di
F000:0F71 pop si
F000:0F72 pop bx
F000:0F73 c22: ; CODE XREF: act_disp_page+77j
F000:0F73 ; video_state+Ej
F000:0F73 pop cx
F000:0F74 pop dx
F000:0F75 pop ds
F000:0F76 pop es ; recover segments
F000:0F77 iret ; all done
F000:0F77 set_mode endp ; sp = 0Eh
F000:0F78 ; keyboard nmi interrupt routine
F000:0F78 ;
F000:0F78 ; this routine obtains control upon an nmi interrupt, which
F000:0F78 ; occurs upon a keystroke from the keyboard.
F000:0F78 ;
F000:0F78 ; this routine will de-serialize the bit stream in order to
F000:0F78 ; get the keyboard scan code entered. it then issues int 48
F000:0F78 ; passing the scan code in al to the key processor . upon return
F000:0F78 ; it re-enables nmi and return to system (iret)
F000:0F78 kdbnmi proc far ; DATA XREF: F000:04D3o
F000:0F78 ; F000:06DCo
F000:0F78 cli
F000:0F79 push si
F000:0F7A push di
F000:0F7B push ax ; save regs
F000:0F7C push bx
F000:0F7D push cx
F000:0F7E push dx
F000:0F7F push ds
F000:0F80 push es
F000:0F81 mov si, 8 ; set up # of data bits
F000:0F84 xor bl, bl ; init parity counter
F000:0F86 xor ah, ah
F000:0F88 mov cx, 5 ; set counter
F000:0F8B i1: ; CODE XREF: kdbnmi:i2j
F000:0F8B in al, 62h ; get sample
F000:0F8D test al, 40h ; test if 1
F000:0F8F jz short i2 ; jmp if 0
F000:0F91 inc ah
F000:0F93 i2: ; CODE XREF: kdbnmi+17j
F000:0F93 loop i1
F000:0F95 cmp ah, 3
F000:0F98 jnb short i25
F000:0F9A jmp short i8
F000:0F9C db 90h ; 
F000:0F9D i25: ; CODE XREF: kdbnmi+20j
F000:0F9D mov cx, 32h ; '2'
F000:0FA0 i3: ; CODE XREF: kdbnmi+2Ej
F000:0FA0 in al, 62h
F000:0FA2 test al, 40h
F000:0FA4 jz short i5
F000:0FA6 loop i3
F000:0FA8 jmp short i8
F000:0FAA db 90h ; 
F000:0FAB i5: ; CODE XREF: kdbnmi+2Cj
F000:0FAB mov al, 1000000b ; read clock
F000:0FAB ; (tim 1, latching, interrupt on terminal count, binary)
F000:0FAD out 43h, al
F000:0FAF nop
F000:0FB0 nop
F000:0FB1 in al, 41h
F000:0FB3 mov ah, al
F000:0FB5 in al, 41h
F000:0FB7 xchg ah, al
F000:0FB9 mov di, ax ; save clock time in di
F000:0FBB mov cx, 4 ; set counter
F000:0FBE i6: ; CODE XREF: kdbnmi+4Cj
F000:0FBE in al, 62h ; get sample
F000:0FC0 test al, 40h ; test if 0
F000:0FC2 jnz short i8 ; jmp if invalid transition (sync)
F000:0FC4 loop i6 ; keep looking for valid transition
F000:0FC6 mov dx, 544 ; 310 usec away (.838 us / ct)
F000:0FC9 i7: ; CODE XREF: kdbnmi+67j
F000:0FC9 call i30
F000:0FCC mov dx, 526
F000:0FCF push ax
F000:0FD0 call i30
F000:0FD3 mov cl, al
F000:0FD5 pop ax
F000:0FD6 cmp cl, al
F000:0FD8 jz short i9
F000:0FDA shr bh, 1
F000:0FDC or bh, al
F000:0FDE dec si
F000:0FDF jnz short i7
F000:0FE1 call i30
F000:0FE4 push ax
F000:0FE5 call i30
F000:0FE8 mov cl, al
F000:0FEA pop ax
F000:0FEB cmp cl, al
F000:0FED jz short i9
F000:0FEF and bl, 1 ; check if odd parity
F000:0FF2 jz short i9 ; jmp if parity error
F000:0FF4 sti ; enable interrupts
F000:0FF5 mov al, bh ; place scan code in al
F000:0FF7 int 48h ; character processing (PCjr - Cordless Keyboard Translation)
F000:0FF9 i8: ; CODE XREF: kdbnmi+22j
F000:0FF9 ; kdbnmi+30j kdbnmi+4Aj
F000:0FF9 ; kdbnmi+92j kdbnmi+B7j
F000:0FF9 pop es ; restore regs
F000:0FFA pop ds
F000:0FFB pop dx
F000:0FFC pop cx
F000:0FFD pop bx
F000:0FFE in al, 0A0h ; enable nmi (clear nmi latch)
F000:1000 pop ax
F000:1001 pop di
F000:1002 pop si
F000:1003 iret
F000:1004 ;----------parity, synch or phase error. output missed key beep
F000:1004 i9: ; CODE XREF: kdbnmi+60j
F000:1004 ; kdbnmi+75j kdbnmi+7Aj
F000:1004 call dss ; set up addressing
F000:1007 cmp si, 8 ; are we on the first data bit?
F000:100A jz short i8 ; no audio feedback (might be a glitch)
F000:100C test byte ptr ds:seg40.kb_flag_1, 1 ; check if transmition errors are to be reported
F000:1011 jnz short i10 ; 1=do not beep, 0=beep
F000:1013 mov bx, 80h ; '€' ; duration of error beep
F000:1016 mov cx, 48h ; 'H' ; frequency of error beep
F000:1019 call kb_noise ; audio feedback
F000:101C and byte ptr ds:seg40.kb_flag, 0F0h ; clear alt,ctrl,left and right shifts
F000:1021 and byte ptr ds:seg40.kb_flag_1, 0Fh ; clear potential break of ins,caps num and scroll shifts
F000:1026 and byte ptr ds:seg40.kb_flag_2, 1Fh ; clear function states
F000:102B i10: ; CODE XREF: kdbnmi+99j
F000:102B inc byte ptr ds:seg40.kdb_error ; keep track of keyboard errors
F000:102F jmp short i8
F000:102F kdbnmi endp
F000:1031 i30 proc near ; CODE XREF: kdbnmi:i7p
F000:1031 ; kdbnmi+58p kdbnmi+69p
F000:1031 ; kdbnmi+6Dp i30+14j
F000:1031 mov al, 1000000b ; read clock
F000:1031 ; (tim 1, latching, interrupt on terminal count, binary)
F000:1033 out 43h, al
F000:1035 nop
F000:1036 nop
F000:1037 in al, 41h
F000:1039 mov ah, al
F000:103B in al, 41h
F000:103D xchg ah, al
F000:103F mov cx, di ; get last clock time
F000:1041 sub cx, ax ; sub current time
F000:1043 cmp cx, dx ; is it time to sample?
F000:1045 jb short i30 ; no, keep looking at it
F000:1047 sub cx, dx ; update # of counts off
F000:1049 mov di, ax ; save current time as last time
F000:104B add di, cx ; add difference for next time
F000:104D ;----- start sampling data bit (5 samples)
F000:104D mov cx, 5 ; set counter
F000:1050 ;----------------------------------------------------
F000:1050 ;
F000:1050 ; sample line
F000:1050 ;
F000:1050 ; port_c is sampled cx times and if there are 3 or more 1"s
F000:1050 ; then 80h is returned in al, else 00h is returned in al.
F000:1050 ; parity counter is mantained in es.
F000:1050 ;
F000:1050 ;----------------------------------------------------
F000:1050 xor ah, ah ; clear counter
F000:1052 i32: ; CODE XREF: i30:i33j
F000:1052 in al, 62h ; get sample
F000:1054 test al, 40h ; test if 1
F000:1056 jz short i33 ; jump if 0
F000:1058 inc ah ; keep count of 1's
F000:105A i33: ; CODE XREF: i30+25j
F000:105A loop i32 ; keep sampling
F000:105C cmp ah, 3 ; valid 1?
F000:105F jb short i34 ; jmp if not valid 1
F000:1061 mov al, 80h ; '€' ; return 80h in al (1)
F000:1063 inc bl ; increment parity counter
F000:1065 retn ; return to caller
F000:1066 i34: ; CODE XREF: i30+2Ej
F000:1066 xor al, al ; return 0 in al (0)
F000:1068 retn ; return to caller
F000:1068 i30 endp
F000:1069 ;-----table of valid scan codes
F000:1069 kb0 db key_b, key_q, key_e, key_p, key_s, key_n, key_up_arrow
F000:1069 ; DATA XREF: key62_int+174o
F000:1069 ; key62_int:kb10_1o
F000:1069 db key_down_arrow, key_left_arrow, key_right_arrow, key_minus
F000:1069 db key_equals
F000:1075 ;-----table of new scan codes (fn + kb0 = kb1)
F000:1075 kb1 db key_break, key_pause, key_echo, key_prt_screen, key_scroll
F000:1075 ; DATA XREF: key62_int+1ABr
F000:1075 db key_num, key_home, key_end, key_page_up, key_page_down
F000:1075 db key_minus_pad, key_plus_pad
F000:1081 ;----------------------------------------------------
F000:1081 ;note: there is a one to one correspondance between
F000:1081 ; the size of kb0 and kb1
F000:1081 ;----------------------------------------------------
F000:1081 ;table of numeric keypad scan codes
F000:1081 ; these scan codes were numeric scan codes on
F000:1081 ; the 83 key keyboard.
F000:1081 ;----------------------------------------------------
F000:1081 num_codes db 4Fh, 50h, 51h, 4Bh, 4Ch, 4Dh, 47h, 48h, 49h, 52h
F000:1081 ; DATA XREF: key62_int+131o
F000:108B ;----------------------------------------------------
F000:108B ;table of simulated keystrokes
F000:108B ;
F000:108B ; this table represents a 4*2 array. each row
F000:108B ; consists of a sequence of scan codes which
F000:108B ; would have been generated on an 83 key keyboard
F000:108B ; to cause the following functions:
F000:108B ; row 1=echo crt output to the printer
F000:108B ; row 2=break
F000:108B ; the table has both make and break scan codes.
F000:108B ;----------------------------------------------------
F000:108B scan db 1Dh, 37h, 0B7h, 9Dh ; DATA XREF: key62_int+212o
F000:108B ; ctrl + prtsc
F000:108F db 1Dh, 46h, 0C6h, 9Dh ; ctrl + scroll_lock
F000:1093 ;----------------------------------------------------
F000:1093 ;table of valid alt shift scan codes
F000:1093 ;
F000:1093 ; this table contains scan codes for keys on the
F000:1093 ; 62 key keyboard. these codes are used in
F000:1093 ; combinations with the alt key to produce scan codes
F000:1093 ; for keys not found on the 62 key keyboard.
F000:1093 ;----------------------------------------------------
F000:1093 alt_table db 35h, 28h, 34h, 1Ah, 1Bh ; DATA XREF: key62_int+B7o
F000:1093 ; key62_int+C1o
F000:1098 ;----------------------------------------------------
F000:1098 ;table of translated scan codes with alt shift
F000:1098 ;
F000:1098 ; this table contains the scan codes for the
F000:1098 ; keys which are not in the 62 key keyboard and
F000:1098 ; will be translated with alt shift. there is a
F000:1098 ; one to one correspondence between the sizes
F000:1098 ; of alt_table and new_alt.
F000:1098 ; the following translations are made:
F000:1098 ; alt+ / = \
F000:1098 ; alt+ ' = `
F000:1098 ; alt+ [ = |
F000:1098 ; alt+ ] = ~
F000:1098 ; alt+ . = #
F000:1098 ;----------------------------------------------------
F000:1098 new_alt db 2Bh, 29h, 37h, 2Bh, 29h ; DATA XREF: key62_int+C6r
F000:109D ;-----------------------------------------------------------
F000:109D ; extab
F000:109D ; table of scan codes for mapping extended set
F000:109D ; of scan codes (scan codes > 85). this table
F000:109D ; allows other devices to use the keyboard interface.
F000:109D ; if the device generates a scan code > 85 this table
F000:109D ; can be used to map the device to the keyboard. the
F000:109D ; device also has the option of having a unioue scan
F000:109D ; code put in the keyboard buffer (instead of mapping
F000:109D ; to the keyboard). the extended scan code put in the
F000:109D ; buffer will be continuous beginning at 150. a zero
F000:109D ; will be used in place of an ascii code (e.g. a
F000:109D ; device generating scan code 86 and not mapping 86
F000:109D ; to the keyboard will have a [150,0] put in the
F000:109D ; keyboard buffer.
F000:109D ; table format:
F000:109D ; the first byte is a length indicating the number
F000:109D ; of scan codes mapped to the keyboard. the remaining
F000:109D ; entries are words. the first byte (low byte) is a
F000:109D ; scan code and the second byte (high byte) is zero.
F000:109D ; a device generating n scan codes is assumed to generate the
F000:109D ; following stream 86,87,88,...,b6+(n-1). the scan code bytes
F000:109D ; in the table correspond to this set with the first data
F000:109D ; byte matching 86, the second matching 87 etc.
F000:109D ; notes:
F000:109D ; (1) if a device generates a break code, nothing is
F000:109D ; put in the buffer
F000:109D ; (2) a length of 0 indicates that zero scan codes have been
F000:109D ; mapped to the keyboard and all extended scan codes will
F000:109D ; be used
F000:109D ; (3) a device can map some of its scan codes to the keyboard
F000:109D ; and have some its scan codes in the extended set
F000:109D ;-----------------------------------------------------------
F000:109D extab db 14h ; DATA XREF: F000:0218o
F000:109E dw 48h, 49h, 4Dh, 51h, 50h, 4Fh, 4Bh, 47h, 39h, 1Ch, 11h
F000:109E dw 12h, 1Fh, 2Dh, 2Ch, 2Bh, 1Eh, 10h, 0Fh, 1
F000:10C6 ; -----------------------------------------------------
F000:10C6 ; key62_int (int 0x48)
F000:10C6 ; the purpose of this routine is to translate scan codes and
F000:10C6 ; scan code combinations from the 62 key keyboard to their
F000:10C6 ; equivalents on the 83 key keyboard. the scan code is
F000:10C6 ; passed in al. each scan code passed either triggers one or
F000:10C6 ; more calls to interrupt 9 or sets flags to retain keyboard
F000:10C6 ; status. when interrupt 9 is called the translated scan
F000:10C6 ; codes are passed to it in al. the intent of this code was
F000:10C6 ; to keep interrupt 9 intact from its origin in the pc family.
F000:10C6 ; this routine is in the front end of interrupt 9 and
F000:10C6 ; transforms a 62 key keyboard to look as if it uere an 83
F000:10C6 ; key version.
F000:10C6 ; it is assumed that this routine is called from the nmi
F000:10C6 ; deserialization routine and that all registers were saved
F000:10C6 ; in the calling routine. as a consequence all registers are
F000:10C6 ; destroyed
F000:10C6 ; -----------------------------------------------------
F000:10C6 key62_int proc far ; DATA XREF: F000:07C9o
F000:10C6 sti
F000:10C7 cld ; forward direction
F000:10C8 call dss ; set up addressing
F000:10CB mov ah, al ; save scan code
F000:10CD call tpm ; adjust output for user modification
F000:10D0 jnb short kbx0 ; jump if ok to continue
F000:10D2 iret ; return from interrupt
F000:10D3 ;-----extended scan code check
F000:10D3 kbx0: ; CODE XREF: key62_int+Aj
F000:10D3 cmp al, 0FFh ; is this an overrun char?
F000:10D5 jz short kb0_1 ; pass it to interrupt 9
F000:10D7 and al, 7Fh ; turn off break bit
F000:10D9 cmp al, 86 ; is this scan code > 86?
F000:10DB jl short kbx4 ; replace break bit
F000:10DD ;-----scan code is in extended set
F000:10DD push ds
F000:10DE xor si, si
F000:10E0 mov ds, si
F000:10E2 les di, ds:124h ; get pointer to extended set (int 0x49)
F000:10E6 mov cl, es:[di] ; get lenght byte
F000:10E9 pop ds
F000:10EA ;-----does scan code get mapped to keyboard or to new extended scan codes?
F000:10EA sub al, 86 ; convert to base to new set
F000:10EC dec cl ; length - 1
F000:10EE cmp al, cl ; is code in table?
F000:10F0 jg short kbx1 ; jump if scan code not in table
F000:10F2 ;-----get scan code from table
F000:10F2 inc di ; point di past length byte
F000:10F3 mov bx, ax
F000:10F5 xor bh, bh ; preparing for adding to 16 bit register
F000:10F7 shl bx, 1
F000:10F9 add di, bx ; offset to correct table entry
F000:10FB mov al, es:[di] ; translated scan code in al
F000:10FE cmp al, 86 ; is code in keyboard set?
F000:1100 jl short kbx4 ; in keyboard set, check for break
F000:1102 ;-----scan code gets mapped to extended scan codes
F000:1102 kbx1: ; CODE XREF: key62_int+2Aj
F000:1102 test ah, 80h ; is this a break code?
F000:1105 jz short kbx2 ; make code, put it in buffer
F000:1107 iret ; break code, return from interrupt
F000:1108 kbx2: ; CODE XREF: key62_int+3Fj
F000:1108 add ah, 64 ; extended set codes begin at 150
F000:110B xor al, al ; zero out ascii value (null)
F000:110D mov bx, ds:seg40.buffer_tail ; get tail pointer
F000:1111 mov si, bx ; save pointer to tail
F000:1113 call k4 ; increment tail value
F000:1116 cmp bx, ds:seg40.buffer_head ; is buffer full?
F000:111A jnz short kbx3 ; put contents of ax in buffer
F000:111C ;-----buffer is full, beep and clear flags
F000:111C mov bx, 80h ; '€' ; frequency of beep
F000:111F mov cx, 48h ; 'H' ; duration of beep
F000:1122 call kb_noise ; buffer full beep
F000:1125 and byte ptr ds:seg40.kb_flag, 0F0h ; clear alt, ctrl, left and right shift
F000:112A and byte ptr ds:seg40.kb_flag_1, 0Fh ; clear make of ins, caps_lock, num and scroll
F000:112F and byte ptr ds:seg40.kb_flag_2, 1Fh ; clear function states
F000:1134 iret ; done with interrupt
F000:1135 kbx3: ; CODE XREF: key62_int+54j
F000:1135 mov [si], ax ; put contents of ax in buffer
F000:1137 mov ds:seg40.buffer_tail, bx ; advance buffer tail
F000:113B iret ; return from interrupt
F000:113C kbx4: ; CODE XREF: key62_int+15j
F000:113C ; key62_int+3Aj
F000:113C and ah, 80h ; mask break bit on original scan
F000:113F or al, ah ; update new scan code
F000:1141 mov ah, al ; save al in ah again
F000:1143 ;------83 key keyboard functions shift+prtsc and ctrl+numlock
F000:1143 kb0_1: ; CODE XREF: key62_int+Fj
F000:1143 cmp al, key_num ; is this a numlock?
F000:1145 jnz short kb0_3 ; check for prtsc
F000:1147 test byte ptr ds:seg40.kb_flag, 100b ; is ctrl key being held down?
F000:114C jz short kb0_2 ; numlock without ctrl, continue
F000:114E test byte ptr ds:seg40.kb_flag, 1000b ; is alt key held currently?
F000:1153 jnz short kb0_2 ; pass it on
F000:1155 jmp kb16_1 ; put keyboard in hold state
F000:1158 kb0_2: ; CODE XREF: key62_int+86j
F000:1158 ; key62_int+8Dj
F000:1158 ; key62_int+9Ej
F000:1158 ; key62_int+A5j
F000:1158 jmp cont_int ; continue with interrupt 0x48
F000:115B ;-----check for prtsc
F000:115B kb0_3: ; CODE XREF: key62_int+7Fj
F000:115B cmp al, 55 ; is this prtsc key?
F000:115D jnz short kb1_1 ; not a prtsc key
F000:115F test byte ptr ds:seg40.kb_flag, 11b ; either shift active?
F000:1164 jz short kb0_2 ; process scan in int9
F000:1166 test byte ptr ds:seg40.kb_flag, 100b ; is ctrl key pressed?
F000:116B jnz short kb0_2 ; not a valid prtsc (pc compatible)
F000:116D jmp prtsc ; handle the print screen function
F000:1170 ;-----alternate shift translations
F000:1170 kb1_1: ; CODE XREF: key62_int+97j
F000:1170 mov ah, al ; save character
F000:1172 and al, 7Fh ; mask break bit
F000:1174 test byte ptr ds:seg40.kb_flag, 1000b ; is this a potential translation?
F000:1179 jz short kb2
F000:117B ;-----table lookup
F000:117B push cs
F000:117C pop es ; initialize segment for table lookup
F000:117D mov di, offset alt_table
F000:1180 mov cx, 5 ; get ready for table lookup
F000:1183 repne scasb ; search table
F000:1185 jnz short kb2 ; jump if match is not found
F000:1187 mov cx, (offset alt_table+1)
F000:118A sub di, cx ; update di to index scan code
F000:118C mov al, cs:new_alt[di] ; translate scan code
F000:1191 ;-----check for break code
F000:1191 mov bl, ds:seg40.kb_flag ; save kb_flag status
F000:1195 xor byte ptr ds:seg40.kb_flag, 1000b ; mask off alt shift
F000:119A test ah, 80h ; is this a break character
F000:119D jz short kb1_2 ; jump if scan is a make
F000:119F or al, 80h ; set break bit
F000:11A1 ;-----make code, check for shift sequence
F000:11A1 kb1_2: ; CODE XREF: key62_int+D7j
F000:11A1 cmp di, 3 ; is this a shift sequence
F000:11A4 jl short kb1_3 ; jump if not a shift sequence
F000:11A6 or byte ptr ds:seg40.kb_flag, 10b ; turn on shift flag
F000:11AB kb1_3: ; CODE XREF: key62_int+DEj
F000:11AB out 60h, al
F000:11AD int 9 ; issue int to process scan code
F000:11AF mov ds:seg40.kb_flag, bl ; restore original flag states
F000:11B3 iret
F000:11B4 ;-----function key handler
F000:11B4 kb2: ; CODE XREF: key62_int+B3j
F000:11B4 ; key62_int+BFj
F000:11B4 cmp al, key_fn ; check for function key (fn_key)
F000:11B6 jnz short kb4 ; jump if not function key
F000:11B8 test ah, 80h ; is this a function break
F000:11BB jnz short kb3 ; jump if function break
F000:11BD and byte ptr ds:seg40.kb_flag_2, 1Fh ; clear all previous functions
F000:11C2 or byte ptr ds:seg40.kb_flag_2, 10100000b ; (fn_flag + fn_pending)
F000:11C7 iret ; return from interrupt
F000:11C8 ;-----function break
F000:11C8 kb3: ; CODE XREF: key62_int+F5j
F000:11C8 test byte ptr ds:seg40.kb_flag_2, 100000b ; (fn_pending)
F000:11CD jnz short kb3_1 ; jump if function is pending
F000:11CF and byte ptr ds:seg40.kb_flag_2, 1Fh ; clear all flags
F000:11D4 iret
F000:11D5 kb3_1: ; CODE XREF: key62_int+107j
F000:11D5 or byte ptr ds:seg40.kb_flag_2, 1000000b ; set break flag (fn_break)
F000:11DA kb3_2: ; CODE XREF: key62_int+117j
F000:11DA iret ; return from interrupt
F000:11DB ;-----check if function flag already set
F000:11DB kb4: ; CODE XREF: key62_int+F0j
F000:11DB cmp al, key_phk ; is this a phantom key? (phk)
F000:11DD jz short kb3_2 ; jump if phantom sequence
F000:11DF test byte ptr ds:seg40.kb_flag_2, 10010000b ; are we in function state? (fn_flag + fn_lock)
F000:11E4 jnz short kb5
F000:11E6 ;-----check if num_state is active
F000:11E6 test byte ptr ds:seg40.kb_flag, 100000b ; (num_state)
F000:11EB jz short kb4_0 ; jump if not in num_state
F000:11ED cmp al, key_num_0 ; are we in numeric keypad region?
F000:11EF ja short kb4_0 ; jump if not in keypad
F000:11F1 dec al ; check lower bound of range
F000:11F3 jz short kb4_0 ; jump if not in range (esc key)
F000:11F5 ;-----translate scan code to numeric keypad
F000:11F5 dec al ; al is offset into table
F000:11F7 mov bx, offset num_codes
F000:11FA xlat byte ptr cs:[bx] ; new scan code is in al
F000:11FC and ah, 80h ; isolate break bit on original scan code
F000:11FF or al, ah ; update keypad scan code
F000:1201 jmp short cont_int ; continue with interrupt
F000:1203 kb4_0: ; CODE XREF: key62_int+125j
F000:1203 ; key62_int+129j
F000:1203 ; key62_int+12Dj
F000:1203 mov al, ah ; get back break bit if set
F000:1205 jmp short cont_int
F000:1207 ;-----check for valid function key
F000:1207 kb5: ; CODE XREF: key62_int+11Ej
F000:1207 cmp al, key_num_0 ; check for range of integers
F000:1209 ja short kb7 ; jump if not in range
F000:120B dec al ; check for esc key (=1)
F000:120D jnz short kb6 ; not escape key, range of integers
F000:120F ;-----escape key, lock keyboard in function lock
F000:120F test ah, 80h ; is this a break code?
F000:1212 jnz short kb8 ; no processing for escape break
F000:1214 test byte ptr ds:seg40.kb_flag_2, 80h ; toggles only when fn held concurrently (fn_flag)
F000:1219 jz short kb8 ; not held concurrently
F000:121B test byte ptr ds:seg40.kb_flag_2, 40h ; has the function key been released (fn_break)
F000:1220 jnz short kb8 ; continue if released. process as esc
F000:1222 test byte ptr ds:seg40.kb_flag, 3 ; either shift? (left_shift+right_shift)
F000:1227 jz short kb8 ; not held down
F000:1229 xor byte ptr ds:seg40.kb_flag_2, 10h ; toggle state (fn_lock)
F000:122E and byte ptr ds:seg40.kb_flag_2, 1Fh ; turn off other states (clear_flags)
F000:1233 iret ; return from interrupt
F000:1234 ;-----scan code in range 1 -> 0
F000:1234 kb6: ; CODE XREF: key62_int+147j
F000:1234 add al, 58 ; generate correct scan code
F000:1236 jmp short kb12 ; clean-up before return to kb_int
F000:1238 ;-----check table for other valid scan codes
F000:1238 kb7: ; CODE XREF: key62_int+143j
F000:1238 push cs
F000:1239 pop es ; establish address of table
F000:123A mov di, offset kb0 ; base of table
F000:123D mov cx, 0Ch ; lenght of table
F000:1240 repne scasb ; search table for a match
F000:1242 jz short kb10 ; jump if match
F000:1244 ;-----illegal character
F000:1244 kb8: ; CODE XREF: key62_int+14Cj
F000:1244 ; key62_int+153j
F000:1244 ; key62_int+15Aj
F000:1244 ; key62_int+161j
F000:1244 ; key62_int+1A4j
F000:1244 test byte ptr ds:seg40.kb_flag_2, 40h
F000:1249 jz short kb9
F000:124B test ah, 80h
F000:124E jnz short kb9
F000:1250 kb85: ; CODE XREF: key62_int+1FCj
F000:1250 and byte ptr ds:seg40.kb_flag_2, 1Fh
F000:1255 mov byte ptr ds:seg40.cur_func, 0
F000:125A ;-----function break is not set
F000:125A kb9: ; CODE XREF: key62_int+183j
F000:125A ; key62_int+188j
F000:125A mov al, ah ; retreive original scancode
F000:125C cont_int: ; CODE XREF: key62_int:kb0_2j
F000:125C ; key62_int+13Bj
F000:125C ; key62_int+13Fj
F000:125C ; key62_int+203j
F000:125C out 60h, al ; AT Keyboard controller 8042.
F000:125E int 9 ; issue keyboard interrupt
F000:1260 ret_int: ; CODE XREF: key62_int+1D0j
F000:1260 ; key62_int+1E1j
F000:1260 iret
F000:1261 ;-----before translation check for alt+fn+n_key as num lock
F000:1261 kb10: ; CODE XREF: key62_int+17Cj
F000:1261 cmp al, key_n ; is this a potention numlock? (n_key)
F000:1263 jnz short kb10_1 ; not a numkey, translate it
F000:1265 test byte ptr ds:seg40.kb_flag, 8 ; alt held down also?
F000:126A jz short kb8 ; treat as illegal combination
F000:126C kb10_1: ; CODE XREF: key62_int+19Dj
F000:126C mov cx, (offset kb0+1) ; get offset to table
F000:126F sub di, cx ; update index to new scancode table
F000:1271 mov al, cs:kb1[di] ; move new scancode into register
F000:1276 ;-----translated code in al or an offset to the table "scan"
F000:1276 kb12: ; CODE XREF: key62_int+170j
F000:1276 test ah, 80h ; is this a break char?
F000:1279 jz short kb13 ; jump if make code
F000:127B ;-----check for toggle key
F000:127B cmp al, key_num ; is this a num lock?
F000:127D jz short kb12_1 ; jump if toggle key
F000:127F cmp al, key_scroll ; is this a scroll lock?
F000:1281 jnz short kb12_2 ; jump if not a toggle key
F000:1283 kb12_1: ; CODE XREF: key62_int+1B7j
F000:1283 or al, 80h ; turn on break bit
F000:1285 out 60h, al
F000:1287 int 9 ; toggle state
F000:1289 and al, 7Fh ; turn off break bit
F000:128B kb12_2: ; CODE XREF: key62_int+1BBj
F000:128B test byte ptr ds:seg40.kb_flag_2, 40h ; has function break occured?
F000:1290 jz short kb12_3 ; jump if break has not occured
F000:1292 cmp al, ds:seg40.cur_func ; is this a break of old valid function
F000:1296 jnz short ret_int ; allow further current functions
F000:1298 and byte ptr ds:seg40.kb_flag_2, 1Fh ; (clear_flags)
F000:129D kb12_20: ; CODE XREF: key62_int+1E8j
F000:129D mov byte ptr ds:seg40.cur_func, 0 ; clear current function
F000:12A2 iret ; return from interrupt
F000:12A3 kb12_3: ; CODE XREF: key62_int+1CAj
F000:12A3 cmp al, ds:seg40.cur_func ; is this break of first function?
F000:12A7 jnz short ret_int ; ignore
F000:12A9 and byte ptr ds:seg40.kb_flag_2, 0DFh ; turn off pending function (and_mask-fn_pending)
F000:12AE jmp short kb12_20 ; clear current function and return
F000:12B0 ;-----valid make key has pressed
F000:12B0 kb13: ; CODE XREF: key62_int+1B3j
F000:12B0 test byte ptr ds:seg40.kb_flag_2, 40h ; check if function key has been pressed
F000:12B5 jz short kb14_1 ; jump if not set
F000:12B7 ;------function break has already occured
F000:12B7 cmp byte ptr ds:seg40.cur_func, 0 ; is this a new function?
F000:12BC jz short kb14_1 ; initialize new function
F000:12BE cmp ds:seg40.cur_func, al ; is this non-current function
F000:12C2 jnz short kb85 ; jump if no function is pending to retreive original scan code
F000:12C4 ;-----check for scan code generation sequence
F000:12C4 kb14_1: ; CODE XREF: key62_int+1EFj
F000:12C4 ; key62_int+1F6j
F000:12C4 mov ds:seg40.cur_func, al ; initialize current fn
F000:12C7 cmp al, key_prt_screen ; is this a simulated sequence?
F000:12C9 jg short cont_int ; jump if this is a simple translation
F000:12CB jz short prtsc ; do the print screen function
F000:12CD cmp al, key_pause ; is this the hold function?
F000:12CF jz short kb16_1
F000:12D1 ;-----break or echo
F000:12D1 dec al ; point at base
F000:12D3 shl al, 1
F000:12D5 shl al, 1 ; multiply by 4
F000:12D7 cbw
F000:12D8 db 2Eh
F000:12D8 lea si, scan ; address sequence of simulated keystrokes
F000:12DD add si, ax ; update to point at correct set
F000:12DF mov cx, 4 ; loop counter
F000:12E2 generate: ; CODE XREF: key62_int+222j
F000:12E2 lods byte ptr cs:[si] ; get scan code from table
F000:12E4 out 60h, al
F000:12E6 int 9 ; process it
F000:12E8 loop generate ; get next
F000:12EA iret
F000:12EB ;-----put keyboard in hold state
F000:12EB kb16_1: ; CODE XREF: key62_int+8Fj
F000:12EB ; key62_int+209j
F000:12EB test byte ptr ds:seg40.kb_flag_1, 8
F000:12F0 jnz short kb16_2
F000:12F2 or byte ptr ds:seg40.kb_flag_1, 8
F000:12F7 in al, 0A0h ; reset keyboard latch
F000:12F9 hold: ; CODE XREF: key62_int+238j
F000:12F9 test byte ptr ds:seg40.kb_flag_1, 8
F000:12FE jnz short hold
F000:1300 kb16_2: ; CODE XREF: key62_int+22Aj
F000:1300 iret
F000:1301 ;-----print screen function
F000:1301 prtsc: ; CODE XREF: key62_int+A7j
F000:1301 ; key62_int+205j
F000:1301 test byte ptr ds:seg40.kb_flag_1, 8 ; is hold state in progress
F000:1306 jz short kb16_3 ; ok to continue with prtsc
F000:1308 and byte ptr ds:seg40.kb_flag_1, 0F7h ; turn off flag
F000:130D iret
F000:130E kb16_3: ; CODE XREF: key62_int+240j
F000:130E add sp, 6 ; get rid of call to interrupt 48h
F000:1311 pop es ; pop registers that aren't modified in int5
F000:1312 pop ds
F000:1313 pop dx
F000:1314 pop cx
F000:1315 pop bx
F000:1316 in al, 0A0h ; reset keyboard latch
F000:1318 int 5 ; issue interrupt
F000:131A pop ax
F000:131B pop di
F000:131C pop si ; pop the rest
F000:131D iret
F000:131D key62_int endp ; sp = 16h
F000:131E ; -----------------------------------------------------
F000:131E ; typamatic
F000:131E ; this routine will check keyboard status bits in kb_flag_2
F000:131E ; and determine what state the keyboard is in. appropriate
F000:131E ; action will be taken.
F000:131E ; input
F000:131E ; al= scan code of key which triggered non-maskable interrupt
F000:131E ; output
F000:131E ; carry bit = 1 if no action is to be taken
F000:131E ; carry bit = 0 means scan code in al should be processed
F000:131E ; further
F000:131E ; modifications to the variables cur_char and var_delay are
F000:131E ; made. also the putchar bit in kb_flag_2 is toggled when
F000:131E ; the keyboard is in half rate mode
F000:131E ; -----------------------------------------------------
F000:131E tpm proc near ; CODE XREF: key62_int+7p
F000:131E push bx
F000:131F cmp ds:seg40.cur_char, al ; is this a new char?
F000:1323 jz short tp2 ; jump if same character
F000:1325 ;-----new character check for break sequences
F000:1325 test al, 80h ; is the new key a break key?
F000:1327 jz short tp0 ; jump if not a break key
F000:1329 and al, 7Fh ; clear break bit
F000:132B cmp ds:seg40.cur_char, al ; is the new character the break of the last make?
F000:132F mov al, ah ; retreive original character
F000:1331 jnz short tp ; jump if not the same character
F000:1333 mov byte ptr ds:seg40.cur_char, 0 ; clear current character
F000:1338 tp: ; CODE XREF: tpm+13j tpm+2Fj
F000:1338 ; tpm+36j tpm+5Cj tpm+68j
F000:1338 clc ; clear carry bit
F000:1339 pop bx
F000:133A retn ; return
F000:133B ;-----initialize new character
F000:133B tp0: ; CODE XREF: tpm+9j
F000:133B mov ds:seg40.cur_char, al ; save new character
F000:133E and byte ptr ds:seg40.var_delay, 0F0h ; clear variable delay
F000:1343 and byte ptr ds:seg40.kb_flag_2, 0FEh ; initial putchar bit as zero
F000:1348 test byte ptr ds:seg40.kb_flag_2, 2 ; are we increasing the initial delay?
F000:134D jz short tp ; default delay
F000:134F or byte ptr ds:seg40.var_delay, 0Fh ; increase the delay by 2x
F000:1354 jmp short tp
F000:1356 ;-----check if we are in typamatic mode and if delay is over
F000:1356 tp2: ; CODE XREF: tpm+5j
F000:1356 test byte ptr ds:seg40.kb_flag_2, 8 ; if typamatic turned off?
F000:135B jnz short tp4 ; jump if typamatic turned off
F000:135D mov bl, ds:seg40.var_delay ; get var_delay
F000:1361 and bl, 0Fh ; mask off high order (screen range)
F000:1364 or bl, bl ; is initial delay over?
F000:1366 jz short tp3 ; jump if delay is over
F000:1368 dec bl ; decrease delay wait by another character
F000:136A and byte ptr ds:seg40.var_delay, 0F0h
F000:136F or ds:seg40.var_delay, bl
F000:1373 jmp short tp4
F000:1375 ;-----check if time to output char
F000:1375 tp3: ; CODE XREF: tpm+48j
F000:1375 test byte ptr ds:seg40.kb_flag_2, 4 ; are we in half rate mode?
F000:137A jz short tp ; jump if we are in normal mode
F000:137C xor byte ptr ds:seg40.kb_flag_2, 1 ; toggle bit
F000:1381 test byte ptr ds:seg40.kb_flag_2, 1 ; is it time to put out a char
F000:1386 jnz short tp ; not time to output character
F000:1388 tp4: ; CODE XREF: tpm+3Dj tpm+55j
F000:1388 stc ; skip this character. set carry flag
F000:1389 pop bx
F000:138A retn
F000:138A tpm endp
F000:138B dss proc near ; CODE XREF: F000:q23p
F000:138B ; F000:loc_F04E4p q35p
F000:138B ; F000:0643p F000:0809p
F000:138B ; video_io:c1p ...
F000:138B push ax
F000:138C mov ax, 40h ; '@'
F000:138F mov ds, ax
F000:1391 pop ax
F000:1392 retn
F000:1392 dss endp
F000:1393 ; --- int 0x1a ----------------------------------------
F000:1393 ; time_of_day/sound source select
F000:1393 ; this routine allows the clock to be set/read
F000:1393 ; an interface for setting the multiplexer for
F000:1393 ; audio source is also provided
F000:1393 ;
F000:1393 ; input
F000:1393 ; (ah) = 0 read the current clock setting
F000:1393 ; return cx = high portion of count
F000:1393 ; dx = low portion of count
F000:1393 ; al = 0 if timer has not passed 24 hours
F000:1393 ; since last read. <> 0 if on another day
F000:1393 ; (ah) = 1 set current clock
F000:1393 ; cx = high portion of count
F000:1393 ; dx = low portion of count
F000:1393 ; (ah) = 80h set up sound multiplexer
F000:1393 ; al =(source of sound) --> "audio out" or rf modulator
F000:1393 ; 00 = 8253 channel 2
F000:1393 ; 01 = cassette input
F000:1393 ; 02 = "audio in" line on i/o channel
F000:1393 ; 03 = complex sound generator chip
F000:1393 ;
F000:1393 ; note: counts occur at the rate of 1193180/65536 counts/sec
F000:1393 ; (out about 18.2 per second -- see equates below)
F000:1393 ; -----------------------------------------------------
F000:1393 time_of_day proc far ; CODE XREF: F000:FE6Ej
F000:1393 ; DATA XREF: F000:FF17o
F000:1393 sti ; interrupts back on
F000:1394 push ds ; save segment
F000:1395 call dss
F000:1398 cmp ah, 80h ; '€' ; ah=80?
F000:139B jz short t4a ; mux_set-up
F000:139D or ah, ah ; ah=0?
F000:139F jz short t2 ; read_time
F000:13A1 dec ah ; ah=1?
F000:13A3 jz short t3 ; set_time
F000:13A5 t1: ; CODE XREF: time_of_day+26j
F000:13A5 ; time_of_day+36j
F000:13A5 ; time_of_day+48j
F000:13A5 sti ; interrupts back on
F000:13A6 pop ds ; recover segment
F000:13A7 iret ; return to caller
F000:13A8 t2: ; CODE XREF: time_of_day+Cj
F000:13A8 cli ; no timer interrupts while reading
F000:13A9 mov al, ds:seg40.timer_ofl
F000:13AC mov byte ptr ds:seg40.timer_ofl, 0 ; get overflow, and reset flag
F000:13B1 mov cx, ds:seg40.timer_high
F000:13B5 mov dx, ds:seg40.timer_low
F000:13B9 jmp short t1 ; tod_return
F000:13BB t3: ; CODE XREF: time_of_day+10j
F000:13BB cli ; no interrupts while writing
F000:13BC mov ds:seg40.timer_low, dx
F000:13C0 mov ds:seg40.timer_high, cx ; set the time
F000:13C4 mov byte ptr ds:seg40.timer_ofl, 0 ; reset overflow
F000:13C9 jmp short t1 ; tod_return
F000:13CB t4a: ; CODE XREF: time_of_day+8j
F000:13CB push cx
F000:13CC mov cl, 5
F000:13CE shl al, cl ; shift parm bits left 5 positions
F000:13D0 xchg al, ah ; save parm
F000:13D2 in al, 61h ; get current port settings
F000:13D4 and al, 10011111b ; isolate mux bits
F000:13D6 or al, ah ; combine port bits/parm bits
F000:13D8 out 61h, al ; set port to new value
F000:13DA pop cx
F000:13DB jmp short t1 ; tod_return
F000:13DB time_of_day endp
F000:13DD ; --- int 0x16 ----------------------------------------
F000:13DD ; keyboard i/o
F000:13DD ; these routines provide keyboard support
F000:13DD ; input
F000:13DD ; (ah)=0 read the next ascii character struck from the
F000:13DD ; keyboard, return the result in (al), scan code in
F000:13DD ; (ah)
F000:13DD ; (ah)=1 set the z flag to indicate if an ascii character is
F000:13DD ; available to be read.
F000:13DD ; (zf)=1 -- no code available
F000:13DD ; (zf)=0 -- code is available
F000:13DD ; (ah)=2 return the current shift status in al register
F000:13DD ; the bit settings for this code are indicated in
F000:13DD ; the equates for kb_flag
F000:13DD ; (ah)=3 set typematic rates. the typematic rate can be
F000:13DD ; changed using the following functions:
F000:13DD ; (al)=0 return to default. restores original
F000:13DD ; state. i.e. typematic on, normal initial
F000:13DD ; delay, and normal typematic rate
F000:13DD ; (al)=1 increase initial delay. this is the
F000:13DD ; delay between the first characters
F000:13DD ; by one half.
F000:13DD ; (al)=2 half_rate. slows typematic character
F000:13DD ; by one half.
F000:13DD ; (al)=3 combines al=1 and al=2. increases
F000:13DD ; initial delay and slows typematic
F000:13DD ; characters by one half.
F000:13DD ; (al)=4 turn off typematic characters. only the
F000:13DD ; first character is honored. all others
F000:13DD ; are ignored.
F000:13DD ; al is range checked. if al<0 or al>4 the state
F000:13DD ; remains the same.
F000:13DD ; ***note*** each time the typematic rates are
F000:13DD ; changed all previous states are removed. i.e. if
F000:13DD ; the keyboard is in the half rate mode and you want
F000:13DD ; to add an increase in typematic delay, you must
F000:13DD ; call this routine with ah=3 and al=3
F000:13DD ; (ah)=4 adjust keyboard by the value in al as follows:
F000:13DD ; (al)=0 turn off keyboard click.
F000:13DD ; (al)=1 turn on keyboard click.
F000:13DD ; al is range checked. the state is unaltered if
F000:13DD ; al <> 1,0.
F000:13DD ; output
F000:13DD ; as noted above, only ax and flags changed
F000:13DD ; all registers retained
F000:13DD ; -----------------------------------------------------
F000:13DD keyboard_io proc far ; CODE XREF: F000:E82Ej
F000:13DD ; DATA XREF: F000:FF0Fo
F000:13DD sti
F000:13DE push ds
F000:13DF push bx
F000:13E0 call dss
F000:13E3 or ah, ah ; ah=0
F000:13E5 jz short k1 ; ascii_read
F000:13E7 dec ah ; ah=1
F000:13E9 jz short k2 ; ascii_status
F000:13EB dec ah ; ah=2
F000:13ED jz short k3 ; shift_status
F000:13EF jmp short k3_1
F000:13F1 k1: ; CODE XREF: keyboard_io+8j
F000:13F1 ; keyboard_io+1Fj
F000:13F1 sti
F000:13F2 nop
F000:13F3 cli
F000:13F4 mov bx, ds:seg40.buffer_head
F000:13F8 cmp bx, ds:seg40.buffer_tail
F000:13FC jz short k1
F000:13FE mov ax, [bx]
F000:1400 call k4
F000:1403 mov ds:seg40.buffer_head, bx
F000:1407 jmp short ret_int_16
F000:1409 k2: ; CODE XREF: keyboard_io+Cj
F000:1409 cli
F000:140A mov bx, ds:seg40.buffer_head
F000:140E cmp bx, ds:seg40.buffer_tail
F000:1412 mov ax, [bx]
F000:1414 sti
F000:1415 pop bx
F000:1416 pop ds
F000:1417 retf 2
F000:141A k3: ; CODE XREF: keyboard_io+10j
F000:141A mov al, ds:seg40.kb_flag
F000:141D jmp short ret_int_16
F000:141F k3_1: ; CODE XREF: keyboard_io+12j
F000:141F dec ah
F000:1421 jz short k3_3 ; ah=3, adjust typematic
F000:1423 dec ah ; range check for ah=4
F000:1425 jnz short ret_int_16 ; illegal function call
F000:1427 or al, al ; turn off keyboard click?
F000:1429 jnz short k3_2 ; jump for range check
F000:142B and byte ptr ds:seg40.kb_flag_1, 0FBh ; turn off click
F000:1430 jmp short ret_int_16
F000:1432 k3_2: ; CODE XREF: keyboard_io+4Cj
F000:1432 cmp al, 1
F000:1434 jnz short ret_int_16
F000:1436 or byte ptr ds:seg40.kb_flag_1, 4 ; turn on keyboard click
F000:143B jmp short ret_int_16
F000:143D k3_3: ; CODE XREF: keyboard_io+44j
F000:143D cmp al, 4
F000:143F jg short ret_int_16
F000:1441 and byte ptr ds:seg40.kb_flag_2, 0F1h ; mask off any old typematic states
F000:1446 shl al, 1 ; shift to proper position
F000:1448 or ds:seg40.kb_flag_2, al
F000:144C ret_int_16: ; CODE XREF: keyboard_io+2Aj
F000:144C ; keyboard_io+40j
F000:144C ; keyboard_io+48j
F000:144C ; keyboard_io+53j
F000:144C ; keyboard_io+57j
F000:144C ; keyboard_io+5Ej ...
F000:144C pop bx
F000:144D pop ds
F000:144E iret
F000:144E keyboard_io endp
F000:144F ; ----- increment a buffer pointer
F000:144F k4 proc near ; CODE XREF: key62_int+4Dp
F000:144F ; keyboard_io+23p
F000:144F ; kb_int+202p kb_int+2C1p
F000:144F inc bx ; move to next word in list
F000:1450 inc bx
F000:1451 cmp bx, ds:seg40.buffer_end ; at the end of buffer?
F000:1455 jnz short k5 ; no, continue
F000:1457 mov bx, ds:seg40.buffer_start ; yes, reset to buffer beginning
F000:145B k5: ; CODE XREF: k4+6j
F000:145B retn
F000:145B k4 endp
F000:145C ;---- table of shift keys and mask values
F000:145C k6 db 52h, 3Ah, 45h, 46h, 38h, 1Dh, 2Ah, 36h ; DATA XREF: kb_int+32o
F000:145C ; kb_int:k17o
F000:1464 ;---- shift_mask table
F000:1464 k7 db 80h, 40h, 20h, 10h, 8, 4, 2, 1 ; DATA XREF: kb_int+45r
F000:146C ;---- scan code tables
F000:146C k8 db 1Bh, 0FFh, 0, 3 dup(0FFh), 1Eh, 4 dup(0FFh), 1Fh, 0FFh
F000:146C ; DATA XREF: kb_int:k42o
F000:146C db 7Fh, 0FFh, 11h, 17h, 5, 12h, 14h, 19h, 15h, 9, 0Fh
F000:146C db 10h, 1Bh, 1Dh, 0Ah, 0FFh, 1, 13h, 4, 6, 7, 8, 0Ah, 0Bh
F000:146C db 0Ch, 4 dup(0FFh), 1Ch, 1Ah, 18h, 3, 16h, 2, 0Eh, 0Dh
F000:146C db 6 dup(0FFh), 20h, 0FFh
F000:14A6 ;---- ctl table scan
F000:14A6 k9 db 5Eh, 5Fh, 60h, 61h, 62h, 63h, 64h, 65h, 66h, 67h, 2 dup(0FFh)
F000:14A6 ; DATA XREF: kb_int+21Do
F000:14A6 db 77h, 0FFh, 84h, 0FFh, 73h, 0FFh, 74h, 0FFh, 75h, 0FFh
F000:14A6 db 76h, 2 dup(0FFh)
F000:14BF ;---- lc table
F000:14BF k10 db 1Bh, 31h, 32h, 33h, 34h, 35h, 36h, 37h, 38h, 39h, 30h
F000:14BF ; DATA XREF: kb_int:k55o
F000:14BF db 2Dh, 3Dh, 8, 9, 71h, 77h, 65h, 72h, 74h, 79h, 75h, 69h
F000:14BF db 6Fh, 70h, 5Bh, 5Dh, 0Dh, 0FFh, 61h, 73h, 64h, 66h, 67h
F000:14BF db 68h, 6Ah, 6Bh, 6Ch, 3Bh, 27h, 60h, 0FFh, 5Ch, 7Ah, 78h
F000:14BF db 63h, 76h, 62h, 6Eh, 6Dh, 2Ch, 2Eh, 2Fh, 0FFh, 2Ah, 0FFh
F000:14BF db 20h, 0FFh
F000:14F9 ;---- vc table
F000:14F9 k11 db 1Bh, 21h, 40h, 23h, 24h, 25h, 5Eh, 26h, 2Ah, 28h, 29h
F000:14F9 ; DATA XREF: kb_int:k47o
F000:14F9 db 5Fh, 2Bh, 8, 0, 51h, 57h, 45h, 52h, 54h, 59h, 55h, 49h
F000:14F9 db 4Fh, 50h, 7Bh, 7Dh, 0Dh, 0FFh, 41h, 53h, 44h, 46h, 47h
F000:14F9 db 48h, 4Ah, 4Bh, 4Ch, 3Ah, 22h, 7Eh, 0FFh, 7Ch, 5Ah, 58h
F000:14F9 db 43h, 56h, 42h, 4Eh, 4Dh, 3Ch, 3Eh, 3Fh, 0FFh, 0, 0FFh
F000:14F9 db 20h, 0FFh
F000:1533 ;---- uc table scan
F000:1533 k12 db 54h, 55h, 56h, 57h, 58h, 59h, 5Ah, 5Bh, 5Ch, 5Dh
F000:1533 ; DATA XREF: kb_int+23Bo
F000:153D ;---- alt table scan
F000:153D k13 db 68h, 69h, 6Ah, 6Bh, 6Ch, 6Dh, 6Eh, 6Fh, 70h, 71h
F000:1547 ;---- num state table
F000:1547 k14 db 37h, 38h, 39h, 2Dh, 34h, 35h, 36h, 2Bh, 31h, 32h, 33h
F000:1547 ; DATA XREF: kb_int+277o
F000:1547 db 30h, 2Eh
F000:1554 ;---- base case table
F000:1554 k15 db 47h, 48h, 49h, 0FFh, 4Bh, 0FFh, 4Dh, 0FFh, 4Fh, 50h
F000:1554 ; DATA XREF: kb_int+25Eo
F000:1554 db 51h, 52h, 53h
F000:1561 ; int 0x09 handler
F000:1561 ; keyboard interrupt routine
F000:1561 kb_int proc far ; CODE XREF: F000:E987j
F000:1561 ; DATA XREF: real_vector_setup+Ao
F000:1561 ; F000:FEF5o
F000:1561 ; FUNCTION CHUNK AT F000:0043 SIZE 00000106 BYTES
F000:1561 sti ; allow further interrupts
F000:1562 push ax
F000:1563 push bx
F000:1564 push cx
F000:1565 push dx
F000:1566 push si
F000:1567 push di
F000:1568 push ds
F000:1569 push es
F000:156A cld ; forward direction
F000:156B call dss
F000:156E mov ah, al ; move scan code in ah
F000:1570 ;----- test for overrun scan code from keyboard
F000:1570 cmp al, 0FFh ; is this an overrun char?
F000:1572 jnz short k16 ; no, test for shift key
F000:1574 mov bx, 80h ; '€' ; duration of error beep
F000:1577 mov cx, 48h ; 'H' ; frequency of tone
F000:157A call kb_noise ; buffer full beep
F000:157D and byte ptr ds:seg40.kb_flag, 0F0h
F000:1582 and byte ptr ds:seg40.kb_flag_1, 0Fh
F000:1587 and byte ptr ds:seg40.kb_flag_2, 1Fh
F000:158C jmp k26
F000:158F ;----- test for shift keys
F000:158F k16: ; CODE XREF: kb_int+11j
F000:158F and al, 7Fh ; test shift
F000:158F ; turn off the break bit
F000:1591 push cs
F000:1592 pop es
F000:1593 mov di, offset k6
F000:1596 mov cx, 8
F000:1599 repne scasb
F000:159B mov al, ah
F000:159D jz short k17
F000:159F jmp k25
F000:15A2 ;----- shift key found
F000:15A2 k17: ; CODE XREF: kb_int+3Cj
F000:15A2 sub di, (offset k6+1)
F000:15A6 mov ah, cs:k7[di]
F000:15AB test al, 80h
F000:15AD jnz short k23
F000:15AF ;----- shift make found, determine set or toggle
F000:15AF cmp ah, 10h
F000:15B2 jnb short k18
F000:15B4 ;----- plain shift key, set shift on
F000:15B4 or ds:seg40.kb_flag, ah
F000:15B8 jmp k26
F000:15BB ;----- toggled shift key, test for 1st make or not
F000:15BB k18: ; CODE XREF: kb_int+51j
F000:15BB test byte ptr ds:seg40.kb_flag, 4
F000:15C0 jnz short k25
F000:15C2 cmp al, 52h ; 'R'
F000:15C4 jnz short k22
F000:15C6 test byte ptr ds:seg40.kb_flag, 8
F000:15CB jnz short k25
F000:15CD test byte ptr ds:seg40.kb_flag, 20h
F000:15D2 jnz short k21
F000:15D4 test byte ptr ds:seg40.kb_flag, 3
F000:15D9 jz short k22
F000:15DB k20: ; CODE XREF: kb_int+85j
F000:15DB mov ax, 5230h ; put out an ascii zero
F000:15DE jmp k57
F000:15E1 k21: ; CODE XREF: kb_int+71j
F000:15E1 test byte ptr ds:seg40.kb_flag, 3
F000:15E6 jz short k20
F000:15E8 k22: ; CODE XREF: kb_int+63j
F000:15E8 ; kb_int+78j
F000:15E8 test ds:seg40.kb_flag_1, ah
F000:15EC jnz short k26
F000:15EE or ds:seg40.kb_flag_1, ah
F000:15F2 xor ds:seg40.kb_flag, ah
F000:15F6 cmp al, 52h ; 'R'
F000:15F8 jnz short k26
F000:15FA mov ax, 5200h
F000:15FD jmp k57 ; put into output buffer
F000:1600 ;----- break shift found
F000:1600 k23: ; CODE XREF: kb_int+4Cj
F000:1600 cmp ah, 10h
F000:1603 jnb short k24
F000:1605 not ah
F000:1607 and ds:seg40.kb_flag, ah
F000:160B cmp al, 0B8h ; '¸'
F000:160D jnz short k26
F000:160F ;----- alternate shift key released, get the value into buffer
F000:160F mov al, ds:seg40.alt_input
F000:1612 xor ah, ah
F000:1614 mov ds:seg40.alt_input, ah
F000:1618 or al, al
F000:161A jz short k26
F000:161C jmp k58
F000:161F k24: ; CODE XREF: kb_int+A2j
F000:161F cmp al, 0BAh ; 'º'
F000:1621 jnz short k24_1
F000:1623 test byte ptr ds:seg40.kb_flag_1, 2
F000:1628 jz short k24_1
F000:162A and byte ptr ds:seg40.kb_flag_1, 0FDh
F000:162F jmp short k26
F000:1631 db 90h ; 
F000:1632 ;----- break or normal toggle
F000:1632 k24_1: ; CODE XREF: kb_int+C0j
F000:1632 ; kb_int+C7j
F000:1632 not ah
F000:1634 and ds:seg40.kb_flag_1, ah
F000:1638 jmp short k26
F000:163A ;----- test for hold state
F000:163A k25: ; CODE XREF: kb_int+3Ej
F000:163A ; kb_int+5Fj kb_int+6Aj
F000:163A cmp al, 80h ; '€'
F000:163C jnb short k26
F000:163E test byte ptr ds:seg40.kb_flag_1, 8
F000:1643 jz short k28
F000:1645 and byte ptr ds:seg40.kb_flag_1, 0F7h
F000:164A k26: ; CODE XREF: kb_int+2Bj
F000:164A ; kb_int+57j kb_int+8Bj
F000:164A ; kb_int+97j kb_int+ACj
F000:164A ; kb_int+B9j ...
F000:164A pop es
F000:164B pop ds
F000:164C pop di
F000:164D pop si
F000:164E pop dx
F000:164F pop cx
F000:1650 pop bx
F000:1651 pop ax
F000:1652 iret
F000:1653 ;----- not in hold state, test for special chars
F000:1653 k28: ; CODE XREF: kb_int+E2j
F000:1653 test byte ptr ds:seg40.kb_flag, 8
F000:1658 jnz short k29
F000:165A jmp k38
F000:165D ;----- test for alt+ctrl key sequences
F000:165D k29: ; CODE XREF: kb_int+F7j
F000:165D test byte ptr ds:seg40.kb_flag, 4 ; test-reset
F000:165D ; are we in control shift also
F000:1662 jz short k31 ; no reset
F000:1664 cmp al, key_del ; shift state is there, test key
F000:1666 jnz short k29_1 ; no_reset
F000:1668 ;----- ctl-alt-del has been found, do i/o cleanup
F000:1668 mov word ptr ds:seg40.reset_flag, 1234h ; set flag for reset function
F000:166E jmp reset ; jump to power on diagnostics
F000:1671 k29_1: ; CODE XREF: kb_int+105j
F000:1671 cmp al, key_ins ; check for reset with diagnostics (ins_key)
F000:1673 jnz short k29_2 ; check for other alt-ctrl-sequences
F000:1675 ;----- alt-ctrl-ins has been found
F000:1675 mov word ptr ds:seg40.reset_flag, 4321h ; set flag for diagnostics
F000:167B jmp reset ; level 1 diagnostics
F000:167E k29_2: ; CODE XREF: kb_int+112j
F000:167E cmp al, key_caps ; check for keyboard click toggle (caps_key)
F000:1680 jnz short k29_3 ; check for screen adjustment
F000:1682 ;----- alt+ctrl+capslock has been found
F000:1682 test byte ptr ds:seg40.kb_flag_1, 2
F000:1687 jnz short k26
F000:1689 xor byte ptr ds:seg40.kb_flag_1, 4 ; toogle key for audio keystroke feedback
F000:168E or byte ptr ds:seg40.kb_flag_1, 2 ; set click_sequence state
F000:1693 jmp short k26 ; interrupt is over
F000:1695 k29_3: ; CODE XREF: kb_int+11Fj
F000:1695 cmp al, key_right_arrow ; adjust screen to the right? (right_arrow)
F000:1697 jnz short k29_4 ; look for right adjustment
F000:1699 call get_pos ; get the # of positions the screen is shifted
F000:169C cmp al, 0FCh ; 'ü' ; is the screen shifted as far as possible?
F000:169E jl short k26 ; out of range
F000:16A0 dec byte ptr ds:seg40.horz_pos ; shift value to the right
F000:16A4 dec al ; decrease range value
F000:16A6 call put_pos ; restore storage location
F000:16A9 jmp short k29_5 ; adjust
F000:16AB k29_4: ; CODE XREF: kb_int+136j
F000:16AB cmp al, key_left_arrow ; adjust screen to the left (left_arrow)
F000:16AD jnz short k31 ; not an alt_ctrl sequence
F000:16AF call get_pos ; get number of positions the screen is shifted
F000:16B2 cmp al, 4 ; is screen shifted as far as possible?
F000:16B4 jg short k26
F000:16B6 inc byte ptr ds:seg40.horz_pos ; shift screen to the left
F000:16BA inc al ; increase number of positions screen is shifted
F000:16BC call put_pos ; put position back in storage
F000:16BF k29_5: ; CODE XREF: kb_int+148j
F000:16BF mov al, 2 ; adjust
F000:16C1 mov dx, 3D4h ; address to crt controller
F000:16C4 out dx, al
F000:16C5 mov al, ds:seg40.horz_pos ; column position
F000:16C8 inc dx ; point at data register
F000:16C9 out dx, al ; mov position
F000:16CA jmp k26
F000:16CD ;----- in alternate shift, reset not found
F000:16CD k31: ; CODE XREF: kb_int+101j
F000:16CD ; kb_int+14Cj
F000:16CD cmp al, 57 ; no-reset
F000:16CD ; test for space key
F000:16CF jnz short k32 ; not there
F000:16D1 mov al, 20h ; ' ' ; set space char
F000:16D3 jmp k57 ; buffer_fill
F000:16D6 ;---- alt input table
F000:16D6 k30 db 52h, 4Fh, 50h, 51h, 4Bh, 4Ch, 4Dh, 47h, 48h, 49h
F000:16D6 ; DATA XREF: kb_int:k32o
F000:16D6 ; kb_int+1A3o
F000:16E0 ;---- super-shift-table
F000:16E0 db 10h, 11h, 12h, 13h, 14h, 15h, 16h, 17h, 18h, 19h, 1Eh
F000:16E0 db 1Fh, 20h, 21h, 22h, 23h, 24h, 25h, 26h, 2Ch, 2Dh, 2Eh
F000:16E0 db 2Fh, 30h, 31h, 32h
F000:16FA k32: ; CODE XREF: kb_int+16Ej
F000:16FA mov di, offset k30
F000:16FD mov cx, 0Ah
F000:1700 repne scasb
F000:1702 jnz short k33
F000:1704 sub di, (offset k30+1)
F000:1708 mov al, ds:seg40.alt_input
F000:170B mov ah, 0Ah
F000:170D mul ah
F000:170F add ax, di
F000:1711 mov ds:seg40.alt_input, al
F000:1714 jmp k26
F000:1717 k33: ; CODE XREF: kb_int+1A1j
F000:1717 mov byte ptr ds:seg40.alt_input, 0
F000:171C mov cx, 1Ah
F000:171F repne scasb
F000:1721 jnz short k34
F000:1723 xor al, al
F000:1725 jmp k57
F000:1728 k34: ; CODE XREF: kb_int+1C0j
F000:1728 cmp al, 2
F000:172A jb short k35
F000:172C cmp al, 0Eh
F000:172E jnb short k35
F000:1730 add ah, 76h ; 'v'
F000:1733 xor al, al
F000:1735 jmp k57
F000:1738 k35: ; CODE XREF: kb_int+1C9j
F000:1738 ; kb_int+1CDj
F000:1738 cmp al, 3Bh ; ';'
F000:173A jnb short k37
F000:173C k36: ; CODE XREF: kb_int+1E0j
F000:173C jmp k26
F000:173F k37: ; CODE XREF: kb_int+1D9j
F000:173F cmp al, 47h ; 'G'
F000:1741 jnb short k36
F000:1743 mov bx, 153Dh
F000:1746 jmp k63
F000:1749 k38: ; CODE XREF: kb_int+F9j
F000:1749 test byte ptr ds:seg40.kb_flag, 4
F000:174E jz short k44
F000:1750 cmp al, 46h ; 'F'
F000:1752 jnz short k41
F000:1754 mov bx, ds:seg40.buffer_head
F000:1758 mov byte ptr ds:seg40.bios_break, 80h ; '€'
F000:175D int 1Bh ; CTRL-BREAK KEY
F000:175F sub ax, ax
F000:1761 mov [bx], ax
F000:1763 call k4
F000:1766 mov ds:seg40.buffer_tail, bx
F000:176A jmp k26
F000:176D k41: ; CODE XREF: kb_int+1F1j
F000:176D cmp al, 37h ; '7'
F000:176F jnz short k42
F000:1771 mov ax, 7200h
F000:1774 jmp short k57
F000:1776 db 90h ; 
F000:1777 k42: ; CODE XREF: kb_int+20Ej
F000:1777 mov bx, offset k8
F000:177A cmp al, 3Bh ; ';'
F000:177C jb short k56
F000:177E mov bx, offset k9
F000:1781 jmp k63
F000:1784 k44: ; CODE XREF: kb_int+1EDj
F000:1784 cmp al, 47h ; 'G'
F000:1786 jnb short k48
F000:1788 test byte ptr ds:seg40.kb_flag, 3
F000:178D jz short k54
F000:178F cmp al, 0Fh
F000:1791 jnz short k46
F000:1793 mov ax, 0F00h
F000:1796 jmp short k57
F000:1798 k46: ; CODE XREF: kb_int+230j
F000:1798 cmp al, 3Bh ; ';'
F000:179A jb short k47
F000:179C mov bx, offset k12
F000:179F jmp k63
F000:17A2 k47: ; CODE XREF: kb_int+239j
F000:17A2 mov bx, offset k11
F000:17A5 jmp short k56
F000:17A7 k48: ; CODE XREF: kb_int+225j
F000:17A7 test byte ptr ds:seg40.kb_flag, 20h
F000:17AC jnz short k52
F000:17AE test byte ptr ds:seg40.kb_flag, 3
F000:17B3 jnz short k53
F000:17B5 k49: ; CODE XREF: kb_int+273j
F000:17B5 cmp al, 4Ah ; 'J'
F000:17B7 jz short k50
F000:17B9 cmp al, 4Eh ; 'N'
F000:17BB jz short k51
F000:17BD sub al, 47h ; 'G'
F000:17BF mov bx, offset k15
F000:17C2 jmp k64
F000:17C5 k50: ; CODE XREF: kb_int+256j
F000:17C5 mov ax, 4A2Dh
F000:17C8 jmp short k57
F000:17CA k51: ; CODE XREF: kb_int+25Aj
F000:17CA mov ax, 4E2Bh
F000:17CD jmp short k57
F000:17CF k52: ; CODE XREF: kb_int+24Bj
F000:17CF test byte ptr ds:seg40.kb_flag, 3
F000:17D4 jnz short k49
F000:17D6 k53: ; CODE XREF: kb_int+252j
F000:17D6 sub al, 46h ; 'F'
F000:17D8 mov bx, offset k14
F000:17DB jmp short k56
F000:17DD k54: ; CODE XREF: kb_int+22Cj
F000:17DD cmp al, 3Bh ; ';'
F000:17DF jb short k55
F000:17E1 xor al, al
F000:17E3 jmp short k57
F000:17E5 k55: ; CODE XREF: kb_int+27Ej
F000:17E5 mov bx, offset k10
F000:17E8 k56: ; CODE XREF: kb_int+21Bj
F000:17E8 ; kb_int+244j kb_int+27Aj
F000:17E8 dec al
F000:17EA xlat byte ptr cs:[bx]
F000:17EC ;----- put character into buffer
F000:17EC k57: ; CODE XREF: kb_int+7Dj
F000:17EC ; kb_int+9Cj kb_int+172j
F000:17EC ; kb_int+1C4j kb_int+1D4j
F000:17EC ; kb_int+213j ...
F000:17EC cmp al, 0FFh ; buffer fill
F000:17EC ; is this an ignore char?
F000:17EE jz short k59 ; yes, do nothing with it
F000:17F0 cmp ah, 0FFh ; look for -1 pseudo scan
F000:17F3 jz short k59 ; near interrupt return
F000:17F5 k58: ; CODE XREF: kb_int+BBj
F000:17F5 test byte ptr ds:seg40.kb_flag, 40h
F000:17FA jz short k61
F000:17FC test byte ptr ds:seg40.kb_flag, 3
F000:1801 jz short k60
F000:1803 cmp al, 41h ; 'A'
F000:1805 jb short k61
F000:1807 cmp al, 5Ah ; 'Z'
F000:1809 ja short k61
F000:180B add al, 20h ; ' '
F000:180D jmp short k61
F000:180F k59: ; CODE XREF: kb_int+28Dj
F000:180F ; kb_int+292j
F000:180F jmp k26
F000:1812 ;----- convert any lower case to upper case
F000:1812 k60: ; CODE XREF: kb_int+2A0j
F000:1812 cmp al, 61h ; 'a' ; lower-to-upper
F000:1812 ; find out if alphabetic
F000:1814 jb short k61 ; not_caps_state
F000:1816 cmp al, 7Ah ; 'z'
F000:1818 ja short k61 ; not_caps_state
F000:181A sub al, 20h ; ' ' ; convert to uppper case ('a' - 'A')
F000:181C k61: ; CODE XREF: kb_int+299j
F000:181C ; kb_int+2A4j kb_int+2A8j
F000:181C ; kb_int+2ACj kb_int+2B3j
F000:181C ; kb_int+2B7j
F000:181C mov bx, ds:seg40.buffer_tail ; not_caps_state
F000:181C ; get the end pointer to the buffer
F000:1820 mov si, bx ; save the value
F000:1822 call k4 ; advance the tail
F000:1825 cmp bx, ds:seg40.buffer_head ; has the buffer wrapped around
F000:1829 jnz short k61_1 ; buffer_full_beep
F000:182B push bx ; save buffer tail
F000:182C mov bx, 80h ; '€' ; duration of error beep
F000:182F mov cx, 48h ; 'H' ; frequency of error beep half tone
F000:1832 call kb_noise ; output noise
F000:1835 and byte ptr ds:seg40.kb_flag, 0F0h ; clear alt,clrl,left and right shifts
F000:183A and byte ptr ds:seg40.kb_flag_1, 0Fh ; clear potential break of ins,caps,num and scroll shift
F000:183F and byte ptr ds:seg40.kb_flag_2, 1Fh ; clear function states
F000:1844 pop bx ; retreive buffer tail
F000:1845 jmp k26 ; return from interrupt
F000:1848 k61_1: ; CODE XREF: kb_int+2C8j
F000:1848 test byte ptr ds:seg40.kb_flag_1, 4 ; is audio feedback enabled?
F000:184D jz short k61_2 ; no, just put in buffer
F000:184F push bx ; save buffer tail value
F000:1850 mov bx, 1 ; duration of click
F000:1853 mov cx, 10h ; frequency of click
F000:1856 call kb_noise ; output audio feedback of key stroke
F000:1859 pop bx ; retreive buffer_tail value
F000:185A k61_2: ; CODE XREF: kb_int+2ECj
F000:185A mov [si], ax ; store the value
F000:185C mov ds:seg40.buffer_tail, bx ; move the pointer up
F000:1860 jmp k26 ; interrupt_return
F000:1863 ;----- translate scan for pseudo scan codes
F000:1863 k63: ; CODE XREF: kb_int+1E5j
F000:1863 ; kb_int+220j kb_int+23Ej
F000:1863 sub al, 59 ; translate-scan
F000:1863 ; convert origin to function keys
F000:1865 k64: ; CODE XREF: kb_int+261j
F000:1865 xlat byte ptr cs:[bx] ; translate-scan-orgd
F000:1865 ; ctl table scan
F000:1867 mov ah, al ; put value into ah
F000:1869 xor al, al ; zero ascii code
F000:186B jmp k57 ; put it into the buffer
F000:186B kb_int endp
F000:186E get_pos proc near ; CODE XREF: kb_int+138p
F000:186E ; kb_int+14Ep
F000:186E push cx
F000:186F mov al, ds:seg40.var_delay
F000:1872 and al, 0F0h ; mask off low nibble
F000:1874 mov cl, 4
F000:1876 sar al, cl
F000:1878 pop cx
F000:1879 retn
F000:1879 get_pos endp
F000:187A put_pos proc near ; CODE XREF: kb_int+145p
F000:187A ; kb_int+15Bp
F000:187A push cx
F000:187B mov cl, 4
F000:187D shl al, cl
F000:187F mov cl, ds:seg40.var_delay
F000:1883 and cl, 0Fh
F000:1886 or al, cl
F000:1888 mov ds:seg40.var_delay, al
F000:188B pop cx
F000:188C retn
F000:188C put_pos endp
F000:188D ; -----------------------------------------------------
F000:188D ; manufactoring activity signal routine - invoked through the timer
F000:188D ; tick routine during manufacturing activities. (accessed through
F000:188D ; int 1ch)
F000:188D ; -----------------------------------------------------
F000:188D mfg_tick proc far ; DATA XREF: F000:d6o
F000:188D ; F000:0302o
F000:188D push ax
F000:188E sub ax, ax ; send a 00 to port 13 as a
F000:1890 out 13h, al ; activity signal
F000:1892 in al, 61h ; flip speaker data to opposite sense
F000:1894 mov ah, al ; save orig setting
F000:1896 and ah, 10011101b ; make sure mux is -> right and isolate speaker bit
F000:1899 not al ; flip all bits
F000:189B and al, 10b ; isolate speaker data bit (now in opposite sense)
F000:189D or al, ah ; combine with orig. data form port b
F000:189F or al, 10000b ; and disable internal speaker
F000:18A1 out 61h, al
F000:18A3 mov al, 20h ; ' ' ; eoi to intr. chip
F000:18A5 out 20h, al
F000:18A7 pop ax
F000:18A8 iret
F000:18A8 mfg_tick endp
F000:18A9 ; -----------------------------------------------------
F000:18A9 ; convert and print ascii code
F000:18A9 ;
F000:18A9 ; al must contain number to be converted.
F000:18A9 ; ax and bx destroyed.
F000:18A9 ; -----------------------------------------------------
F000:18A9 xpc_byte proc near ; CODE XREF: e_msg+70p
F000:18A9 ; e_msg+76p rom_check+33p
F000:18A9 push ax
F000:18AA mov cl, 4
F000:18AC shr al, cl
F000:18AE call xlat_pr
F000:18B1 pop ax
F000:18B2 and al, 0Fh
F000:18B2 xpc_byte endp
F000:18B4 xlat_pr proc near ; CODE XREF: xpc_byte+5p
F000:18B4 add al, 90h ; ''
F000:18B6 daa
F000:18B7 adc al, 40h ; '@'
F000:18B9 daa
F000:18B9 xlat_pr endp
F000:18BA prt_hex proc near ; CODE XREF: q35+2Ep q35+3Dp
F000:18BA ; e_msg+2Fp e_msg+54p
F000:18BA ; p_msg+5p
F000:18BA push bx
F000:18BB mov ah, 0Eh
F000:18BD mov bh, 0
F000:18BF int 10h
F000:18C1 pop bx
F000:18C2 retn
F000:18C2 prt_hex endp
F000:18C3 ; START OF FUNCTION CHUNK FOR printer_io
F000:18C3 reprint: ; CODE XREF: printer_io+1Cj
F000:18C3 sub dx, dx
F000:18C5 test ch, 4
F000:18C8 jz short loc_F18CB
F000:18CA inc dx
F000:18CB loc_F18CB: ; CODE XREF: printer_io-D70Aj
F000:18CB or ah, ah
F000:18CD jz short loc_F1910
F000:18CF dec ah
F000:18D1 jz short loc_F18F0
F000:18D3 dec ah
F000:18D5 jnz short loc_F18ED
F000:18D7 push ax
F000:18D8 mov ah, 3
F000:18DA ; DX = port number (0-3)
F000:18DA ; Return: AX = port status code
F000:18DC call fake
F000:18DF pop ax
F000:18E0 or dh, dh
F000:18E2 jz short loc_F18EB
F000:18E4 mov ah, dh
F000:18E6 and ah, 0FEh
F000:18E9 jmp short loc_F18ED
F000:18EB loc_F18EB: ; CODE XREF: printer_io-D6F0j
F000:18EB mov ah, 90h ; ''
F000:18ED loc_F18ED: ; CODE XREF: printer_io-D6FDj
F000:18ED ; printer_io-D6E9j
F000:18ED ; printer_io-D6C8j
F000:18ED ; printer_io-D6C4j
F000:18ED ; printer_io-D6B3j
F000:18ED ; printer_io-D6AFj
F000:18ED jmp loc_FF00D
F000:18F0 loc_F18F0: ; CODE XREF: printer_io-D701j
F000:18F0 mov si, dx
F000:18F2 mov al, ds:78h
F000:18F5 add al, 0Ah
F000:18F7 mov [si+7Ch], al
F000:18FB push ax
F000:18FC mov al, 87h ; '‡'
F000:18FE sub ah, ah
F000:1900 int 14h ; SERIAL I/O - INITIALIZE USART
F000:1900 ; AL = initializing parameters, DX = port number (0-3)
F000:1900 ; Return: AH = RS-232 status code bits, AL = modem status bits
F000:1902 call fake
F000:1905 pop ax
F000:1906 mov ah, dh
F000:1908 or ah, ah
F000:190A jz short loc_F18ED
F000:190C mov ah, 0A8h ; '¨'
F000:190E jmp short loc_F18ED
F000:1910 loc_F1910: ; CODE XREF: printer_io-D705j
F000:1910 push ax
F000:1911 mov ah, 1
F000:1913 ; AL = character, DX = port number (0-3)
F000:1913 ; Return: AH = RS-232 status code bits, AL = modem status bits
F000:1915 call fake
F000:1918 pop ax
F000:1919 or dh, dh
F000:191B jz short loc_F1921
F000:191D mov ah, dh
F000:191F jmp short loc_F18ED
F000:1921 loc_F1921: ; CODE XREF: printer_io-D6B7j
F000:1921 mov ah, 10h
F000:1923 jmp short loc_F18ED
F000:1923 ; END OF FUNCTION CHUNK FOR printer_io
F000:1925 fake proc near ; CODE XREF: printer_io-D6F6p
F000:1925 ; printer_io-D6D0p
F000:1925 ; printer_io-D6BDp
F000:1925 xor dh, dh
F000:1927 test ah, 1Eh
F000:192A jz short b13_1
F000:192C mov dh, 8
F000:192E retn
F000:192F b13_1: ; CODE XREF: fake+5j
F000:192F test ah, 80h
F000:1932 jz short b13_2
F000:1934 mov dh, 9
F000:1936 b13_2: ; CODE XREF: fake+Dj
F000:1936 retn
F000:1936 fake endp
F000:1937 ; -----------------------------------------------------
F000:1937 ; new_int9
F000:1937 ; this routine is the interrupt 9 handler when the machine is
F000:1937 ; first powered on and cassette basic is given control. it
F000:1937 ; handles the first keystrokes entered from the keyboard and
F000:1937 ; performs "special" actions as follows:
F000:1937 ; if esc is the first key enetered mini-welcome is
F000:1937 ; executed
F000:1937 ; if ctrl-esc is the first sequence "load cas1",r" is
F000:1937 ; executed giving the user the ability to boot
F000:1937 ; from cassette
F000:1937 ; after these keystrokes or after any other keystrokes the
F000:1937 ; interrupt 9 vector is changed to point at the real
F000:1937 ; interrupt 9 routine.
F000:1937 ; -----------------------------------------------------
F000:1937 new_int_9 proc far ; DATA XREF: bas_ent+4o
F000:1937 cmp al, 1 ; is this an escape key?
F000:1939 jz short esc_key ; jump if al=esc key
F000:193B cmp al, key_ctl ; else, is this a control key?
F000:193D jz short ctrl_key ; jump if al=ctrl key
F000:193F call real_vector_setup ; otherwise initialize real int 9 vector
F000:1942 int 9 ; pass the scan code in al
F000:1944 iret ; return to interrupt 0x48
F000:1945 ctrl_key: ; CODE XREF: new_int_9+6j
F000:1945 or byte ptr ds:seg40.kb_flag, 4 ; turn on ctrl shift in kb_flag
F000:194A iret ; return to interrupt
F000:194B esc_key: ; CODE XREF: new_int_9+2j
F000:194B test byte ptr ds:seg40.kb_flag, 4 ; has control shift occured?
F000:1950 jz short esc_only ; no. escape only
F000:1952 ;control escape has occured, put message in buffer for cassette
F000:1952 ;load
F000:1952 mov byte ptr ds:seg40.kb_flag, 0 ; zero out control state
F000:1957 push ds
F000:1958 pop es ; initialize es for bios data
F000:1959 push ds ; save old ds
F000:195A push cs ; point ds at code segment
F000:195B pop ds
F000:195C mov si, offset cas_load ; get message
F000:195F mov di, 1Eh ; point at keyboard buffer
F000:1962 mov cx, 0Fh ; lenght of cassette message
F000:1965 nop
F000:1966 t_loop: ; CODE XREF: new_int_9+31j
F000:1966 lodsb ; get ascii character from message
F000:1967 stosw ; put in keyboard buffer
F000:1968 loop t_loop
F000:196A pop ds ; retreive bios data segment
F000:196B ;-----initialize queue so message will be removed from buffer
F000:196B mov word ptr ds:seg40.buffer_head, 1Eh ; (kb_buffer)
F000:1971 mov word ptr ds:seg40.buffer_tail, 3Ch ; '<' ; (kb_buffer+cas_lenght*2)
F000:1977 ;----------------------------------------------------
F000:1977 ;***note***
F000:1977 ; it is assumed that the lenght of the cassette message is
F000:1977 ; less than or equal to the lenght of the buffer. if this is
F000:1977 ; not the case the buffer will eventually consume memory.
F000:1977 ;----------------------------------------------------
F000:1977 call real_vector_setup
F000:197A iret
F000:197B esc_only: ; CODE XREF: new_int_9+19j
F000:197B call real_vector_setup
F000:197E mov cx, offset mini
F000:1981 jmp cx ; enter the world of keyboard caper
F000:1981 new_int_9 endp
F000:1983 ;-----message for output when control-escape is entered as first
F000:1983 ; key sequence
F000:1983 cas_load db 'LOAD "CAS1:",R',0Dh ; DATA XREF: new_int_9+25o
F000:1992 write_tty proc far ; CODE XREF: video_io+38j
F000:1992 ; DATA XREF: F000:0D05o
F000:1992 push ax
F000:1993 push ax
F000:1994 mov bh, ds:seg40.active_page
F000:1998 push bx
F000:1999 mov bl, bh
F000:199B xor bh, bh
F000:199D shl bx, 1
F000:199F mov dx, [bx+50h]
F000:19A3 pop bx
F000:19A4 pop ax
F000:19A5 cmp al, 8
F000:19A7 jz short loc_F19F9
F000:19A9 cmp al, 0Dh
F000:19AB jz short loc_F1A01
F000:19AD cmp al, 0Ah
F000:19AF jz short loc_F19C6
F000:19B1 cmp al, 7
F000:19B3 jz short loc_F1A05
F000:19B5 mov ah, 0Ah
F000:19B7 mov cx, 1
F000:19BA ; AL = character, BH = display page - alpha mode
F000:19BA ; BL = color of character (graphics mode, PCjr only)
F000:19BA ; CX = number of times to write character
F000:19BC inc dl
F000:19BE cmp dl, ds:seg40.crt_cols
F000:19C2 jnz short loc_F19F5
F000:19C4 xor dl, dl
F000:19C6 loc_F19C6: ; CODE XREF: write_tty+1Dj
F000:19C6 cmp dh, 18h
F000:19C9 jnz short loc_F19F3
F000:19CB mov ah, 2
F000:19CD ; DH,DL = row, column (0,0 = upper left)
F000:19CD ; BH = page number
F000:19CF mov al, ds:seg40.crt_mode
F000:19D2 cmp al, 4
F000:19D4 jb short loc_F19DA
F000:19D6 xor bh, bh
F000:19D8 jmp short loc_F19E0
F000:19DA loc_F19DA: ; CODE XREF: write_tty+42j
F000:19DA mov ah, 8
F000:19DC ; BH = display page
F000:19DC ; Return: AL = character
F000:19DC ; AH = attribute of character (alpha modes)
F000:19DE mov bh, ah
F000:19E0 loc_F19E0: ; CODE XREF: write_tty+46j
F000:19E0 mov ax, 601h
F000:19E3 sub cx, cx
F000:19E5 mov dh, 18h
F000:19E7 mov dl, ds:seg40.crt_cols
F000:19EB dec dl
F000:19ED loc_F19ED: ; CODE XREF: write_tty+65j
F000:19ED int 10h ; - VIDEO - SCROLL PAGE UP
F000:19ED ; AL = number of lines to scroll window (0 = blank whole window)
F000:19ED ; BH = attributes to be used on blanked lines
F000:19ED ; CH,CL = row,column of upper left corner of window to scroll
F000:19ED ; DH,DL = row,column of lower right corner of window
F000:19EF loc_F19EF: ; CODE XREF: write_tty+78j
F000:19EF pop ax
F000:19F0 jmp video_return
F000:19F3 loc_F19F3: ; CODE XREF: write_tty+37j
F000:19F3 inc dh
F000:19F5 loc_F19F5: ; CODE XREF: write_tty+30j
F000:19F5 ; write_tty+69j
F000:19F5 ; write_tty+6Dj
F000:19F5 ; write_tty+71j
F000:19F5 mov ah, 2
F000:19F7 jmp short loc_F19ED
F000:19F9 loc_F19F9: ; CODE XREF: write_tty+15j
F000:19F9 or dl, dl
F000:19FB jz short loc_F19F5
F000:19FD dec dl
F000:19FF jmp short loc_F19F5
F000:1A01 loc_F1A01: ; CODE XREF: write_tty+19j
F000:1A01 xor dl, dl
F000:1A03 jmp short loc_F19F5
F000:1A05 loc_F1A05: ; CODE XREF: write_tty+21j
F000:1A05 mov bl, 2
F000:1A07 call beep
F000:1A0A jmp short loc_F19EF
F000:1A0A write_tty endp
F000:1A0C ; dl = number of times to beep
F000:1A0C err_beep proc near ; CODE XREF: F000:08CDp
F000:1A0C ; F000:08DDp
F000:1A0C pushf
F000:1A0D push bx
F000:1A0E cli
F000:1A0F g3: ; CODE XREF: err_beep+Cj
F000:1A0F mov bl, 1
F000:1A11 call beep
F000:1A14 g4: ; CODE XREF: err_beep:g4j
F000:1A14 loop g4
F000:1A16 dec dl
F000:1A18 jnz short g3
F000:1A1A g5: ; CODE XREF: err_beep:g5j
F000:1A1A loop g5
F000:1A1C g6: ; CODE XREF: err_beep:g6j
F000:1A1C loop g6
F000:1A1E pop bx
F000:1A1F popf
F000:1A20 retn
F000:1A20 err_beep endp
F000:1A21 video_set_cursor_pos proc near ; CODE XREF: prtn3_int_82:set_cur_pos_and_printp
F000:1A21 ; prtn3_int_82:set_cur_pos_and_exitp
F000:1A21 mov ah, 2
F000:1A23 push di
F000:1A24 push si
F000:1A25 int 10h ; - VIDEO - SET CURSOR POSITION
F000:1A25 ; DH,DL = row, column (0,0 = upper left)
F000:1A25 ; BH = page number
F000:1A27 pop si
F000:1A28 pop di
F000:1A29 retn
F000:1A29 video_set_cursor_pos endp
F000:1A2A ; print something using basic strings
F000:1A2A ; bp = pointer to bas string
F000:1A2A ; dh = row bit7 bit6 special meaning
F000:1A2A ; dl = col
F000:1A2A ; bl = char attribute
F000:1A2A ; Attributes: bp-based frame
F000:1A2A prtn3_int_82 proc far ; DATA XREF: F000:0244o
F000:1A2A push ax
F000:1A2B push es
F000:1A2C push bp
F000:1A2D mov bp, sp
F000:1A2F mov ax, [bp+8]
F000:1A32 mov es, ax
F000:1A34 pop bp
F000:1A35 push bx
F000:1A36 push cx
F000:1A37 push bp
F000:1A38 push si
F000:1A39 push di
F000:1A3A push ds
F000:1A3B push dx
F000:1A3C call dss
F000:1A3F mov bh, ds:seg40.active_page
F000:1A43 xor cx, cx
F000:1A45 start_again: ; CODE XREF: prtn3_int_82+70j
F000:1A45 ; prtn3_int_82+102j
F000:1A45 mov di, 1 ; offset to pattern
F000:1A48 mov al, es:[bp+0] ; pattern len
F000:1A4C xor ah, ah
F000:1A4E mov si, ax ; pattern len in si
F000:1A50 test dh, 80h ; '€' ; bit 7 = on -> use custom attrib
F000:1A53 jnz short skip_attrib
F000:1A55 mov bl, 111b ; attrib 7 = white
F000:1A57 skip_attrib: ; CODE XREF: prtn3_int_82+29j
F000:1A57 test dh, 40h ; bit 6 = off -> regural version
F000:1A5A jz short do_reg_version
F000:1A5C inc si ; len + 1
F000:1A5D and dx, 1F7Fh ; row = 0-31. col=0-127
F000:1A61 l1: ; CODE XREF: prtn3_int_82+8Aj
F000:1A61 inc cl ; total read +1
F000:1A63 dec di ; attrib offset = 0 (?)
F000:1A64 not si ; len is in not'ed. re-not it.
F000:1A66 add si, 2
F000:1A69 next_char: ; CODE XREF: prtn3_int_82+4Fj
F000:1A69 ; prtn3_int_82+57j
F000:1A69 ; prtn3_int_82+66j
F000:1A69 ; prtn3_int_82+CAj
F000:1A69 inc di ; offset + 1
F000:1A6A inc si ; len-1
F000:1A6B jz short _set_cur_pos_and_exit
F000:1A6D mov al, es:[bp+di] ; al = char from user buffer
F000:1A70 cmp al, 0Dh ; carriage return?
F000:1A72 jnz short not_cr
F000:1A74 add dh, 1 ; dh = row++
F000:1A74 ; dl = col = 0
F000:1A77 mov dl, 0
F000:1A79 jmp short next_char
F000:1A7B not_cr: ; CODE XREF: prtn3_int_82+48j
F000:1A7B cmp al, 0Ah ; line feed?
F000:1A7D jnz short not_linefeed
F000:1A7F inc dh ; row ++
F000:1A81 jmp short next_char
F000:1A83 not_linefeed: ; CODE XREF: prtn3_int_82+53j
F000:1A83 cmp al, 0Bh ; vertical tab?
F000:1A85 jnz short not_vt
F000:1A87 inc dh ; row ++
F000:1A89 inc si ; next char
F000:1A8A inc di
F000:1A8B mov al, es:[bp+di]
F000:1A8E add dl, al ; col += char from buffer
F000:1A90 jmp short next_char
F000:1A92 not_vt: ; CODE XREF: prtn3_int_82+5Bj
F000:1A92 cmp al, 0Ch ; form feed?
F000:1A94 jnz short set_cur_pos_and_print
F000:1A96 inc di
F000:1A97 inc di
F000:1A98 add bp, di ; bp += 2
F000:1A9A jmp short start_again
F000:1A9C do_reg_version: ; CODE XREF: prtn3_int_82+30j
F000:1A9C and dx, 1F7Fh ; row = 0-31. col=0-127
F000:1AA0 reg_version_loop: ; CODE XREF: prtn3_int_82+D6j
F000:1AA0 ; prtn3_int_82+E1j
F000:1AA0 ; prtn3_int_82+EAj
F000:1AA0 ; prtn3_int_82+FDj
F000:1AA0 mov cl, es:[bp+si] ; cl = control code
F000:1AA3 inc si ; si = offset + 1
F000:1AA4 cmp cl, 0 ; cl == 0 ?
F000:1AA7 jz short ctl_is_0
F000:1AA9 jl short ctl_is_g_than_128
F000:1AAB cmp cl, 51h ; 'Q'
F000:1AAE jl short set_cur_pos_and_print
F000:1AB0 jmp short check_more_ctrl_codes
F000:1AB2 ctl_is_g_than_128: ; CODE XREF: prtn3_int_82+7Fj
F000:1AB2 inc cl
F000:1AB4 jz short l1 ; cl = 0xff ?
F000:1AB6 inc cl
F000:1AB8 jz short reset_pattern_offset ; cl = 0xfe ?
F000:1ABA inc cl
F000:1ABC jz short update_row ; cl = 0xfd ?
F000:1ABE inc cl
F000:1AC0 jz short _set_cur_pos_and_exit ; cl = 0xfc ?
F000:1AC2 inc cl
F000:1AC4 jz short new_row ; cl = 0xfb ?
F000:1AC6 inc cl
F000:1AC8 jz short start_new_pattern ; cl = 0xfa
F000:1ACA sub cx, 6 ; restore orignal cx value (before the inc's)
F000:1ACD check_more_ctrl_codes: ; CODE XREF: prtn3_int_82+86j
F000:1ACD sub cl, 51h ; 'Q'
F000:1AD0 cmp cl, 50h ; 'P'
F000:1AD3 jl short update_col
F000:1AD5 sub cl, 50h ; 'P'
F000:1AD8 cmp cl, 51h ; 'Q'
F000:1ADB jl short update_attrib_and_print
F000:1ADD _set_cur_pos_and_exit: ; CODE XREF: prtn3_int_82+41j
F000:1ADD ; prtn3_int_82+96j
F000:1ADD jmp short set_cur_pos_and_exit
F000:1ADF set_cur_pos_and_print: ; CODE XREF: prtn3_int_82+6Aj
F000:1ADF ; prtn3_int_82+84j
F000:1ADF ; prtn3_int_82+F2j
F000:1ADF call video_set_cursor_pos
F000:1AE2 push di
F000:1AE3 push si
F000:1AE4 mov ah, 9
F000:1AE6 mov al, es:[bp+di] ; al = char to print (pattern)
F000:1AE9 add dl, cl ; update column w/times char is written
F000:1AEB ; AL = character, BH = display page
F000:1AEB ; BL = attributes of character (alpha modes) or color (graphics modes)
F000:1AEB ; CX = number of times to write character
F000:1AED pop si
F000:1AEE pop di
F000:1AEF ctl_is_0: ; CODE XREF: prtn3_int_82+7Dj
F000:1AEF ; prtn3_int_82+F0j
F000:1AEF cmp si, 0
F000:1AF2 jge short check_pattern
F000:1AF4 jmp next_char
F000:1AF7 check_pattern: ; CODE XREF: prtn3_int_82+C8j
F000:1AF7 mov al, es:[bp+0] ; fetch pattern len
F000:1AFB xor ah, ah
F000:1AFD inc di ; pattern offset ++
F000:1AFE cmp ax, di ; end of pattern?
F000:1B00 jg short reg_version_loop
F000:1B02 jmp short reset_pattern_offset
F000:1B04 new_row: ; CODE XREF: prtn3_int_82+9Aj
F000:1B04 mov dl, 0 ; col = 0
F000:1B06 inc dh ; next row
F000:1B08 reset_pattern_offset: ; CODE XREF: prtn3_int_82+8Ej
F000:1B08 ; prtn3_int_82+D8j
F000:1B08 mov di, 1 ; reset pattern offset
F000:1B0B jmp short reg_version_loop
F000:1B0D update_col: ; CODE XREF: prtn3_int_82+A9j
F000:1B0D sub cl, 40
F000:1B10 add dl, cl ; update col
F000:1B12 inc dh ; row++
F000:1B14 jmp short reg_version_loop
F000:1B16 update_attrib_and_print: ; CODE XREF: prtn3_int_82+B1j
F000:1B16 mov bl, es:[bp+di] ; get attrib value
F000:1B19 inc di ; pattern offset++
F000:1B1A jz short ctl_is_0 ; is it 0? (overflow?)
F000:1B1C jmp short set_cur_pos_and_print
F000:1B1E update_row: ; CODE XREF: prtn3_int_82+92j
F000:1B1E mov ah, es:[bp+si] ; ah = ctrl from buffer
F000:1B21 inc si ; ctl offset++
F000:1B22 sub ah, 40
F000:1B25 add dh, ah ; row += ah
F000:1B27 jmp reg_version_loop
F000:1B2A start_new_pattern: ; CODE XREF: prtn3_int_82+9Ej
F000:1B2A add bp, si
F000:1B2C jmp start_again
F000:1B2F set_cur_pos_and_exit: ; CODE XREF: prtn3_int_82:_set_cur_pos_and_exitj
F000:1B2F call video_set_cursor_pos
F000:1B32 pop bx
F000:1B33 push bx
F000:1B34 test bh, 20h
F000:1B37 jz short read_char_y_n
F000:1B39 test bh, 80h
F000:1B3C jz short beep_1
F000:1B3E mov bl, 3 ; long beep
F000:1B40 call beep
F000:1B43 jmp short read_char_y_n
F000:1B45 beep_1: ; CODE XREF: prtn3_int_82+112j
F000:1B45 mov bl, 1 ; short beep
F000:1B47 call beep
F000:1B4A read_char_y_n: ; CODE XREF: prtn3_int_82+10Dj
F000:1B4A ; prtn3_int_82+119j
F000:1B4A pop bx
F000:1B4B test bl, 80h
F000:1B4E jz short exit
F000:1B50 mov ah, 0
F000:1B52 ; Return: AH = scan code, AL = character
F000:1B54 cmp al, 59h ; 'Y'
F000:1B56 clc
F000:1B57 jnz short exit
F000:1B59 stc
F000:1B5A exit: ; CODE XREF: prtn3_int_82+124j
F000:1B5A ; prtn3_int_82+12Dj
F000:1B5A pop ds
F000:1B5B pop di
F000:1B5C pop si
F000:1B5D pop bp
F000:1B5E pop cx
F000:1B5F pop bx
F000:1B60 pop es
F000:1B61 pop ax
F000:1B62 iret
F000:1B62 prtn3_int_82 endp
F000:1B63 ; does something with row/cols...then prints '*'
F000:1B63 ; input:
F000:1B63 ; al = col used for ??
F000:1B63 ;
F000:1B63 locate_1_int_81 proc far ; DATA XREF: F000:023Eo
F000:1B63 push bx
F000:1B64 push bp
F000:1B65 push ax
F000:1B66 mov bh, 7 ; page number
F000:1B68 l0: ; CODE XREF: locate_1_int_81+12j
F000:1B68 mov ah, 3
F000:1B6A ; BH = page number
F000:1B6A ; Return: DH,DL = row,column, CH = cursor start line, CL = cursor end line
F000:1B6C pop ax
F000:1B6D push ax
F000:1B6E cmp dh, 20 ; row < 20?
F000:1B71 jl short found
F000:1B73 dec bh ; page--
F000:1B75 jmp short l0
F000:1B77 found: ; CODE XREF: locate_1_int_81+Ej
F000:1B77 mov ah, 38 ; max col (?)
F000:1B79 sub ah, dl ; 38 - current col
F000:1B7B cmp al, ah
F000:1B7D jl short end
F000:1B7F mov dl, 2
F000:1B81 add dh, 12
F000:1B84 cmp dh, 20
F000:1B87 jl short end
F000:1B89 mov dx, 1525h ; row=21, col=37
F000:1B8C mov bp, offset unk_F1BA0
F000:1B8F int 82h ; reserved for BASIC
F000:1B91 dec bh
F000:1B93 mov al, bh
F000:1B95 mov ah, 5
F000:1B97 int 10h ; - VIDEO - SELECT DISPLAY PAGE
F000:1B97 ; AL = display page, 0-7 for modes 0 & 1, 0-3 for modes 2 & 3
F000:1B99 mov dx, 102h
F000:1B9C end: ; CODE XREF: locate_1_int_81+1Aj
F000:1B9C ; locate_1_int_81+24j
F000:1B9C pop ax
F000:1B9D pop bp
F000:1B9E pop bx
F000:1B9F iret
F000:1B9F locate_1_int_81 endp
F000:1BA0 unk_F1BA0 db 2 ; DATA XREF: locate_1_int_81+29o
F000:1BA1 db 2Ah ; *
F000:1BA2 db 0FFh
F000:1BA3 db 0
F000:1BA4 db 0FCh ; ü
F000:1BA5 ; int 0x89
F000:1BA5 ; test joystick
F000:1BA5 ; input:
F000:1BA5 ; ah = '6', '7' (official test)
F000:1BA5 ; = 'E' or 0xff (mfg test)
F000:1BA5 ; = 0 (err msg)
F000:1BA5 ; = 1 (another err msg)
F000:1BA5 ; output:
F000:1BA5 ; dl/dh = error msg
F000:1BA5 int_89_diag_joystick proc far ; DATA XREF: F000:024Ao
F000:1BA5 xor bx, bx
F000:1BA7 or ah, ah
F000:1BA9 jz short error_and_exit0
F000:1BAB cmp ah, 1
F000:1BAE jz short error_and_exit1
F000:1BB0 cmp ah, 36h ; '6'
F000:1BB3 jz short run_test_67
F000:1BB5 cmp ah, 45h ; 'E'
F000:1BB8 jz short run_test_e
F000:1BBA cmp ah, 0FFh
F000:1BBD jz short run_test_e
F000:1BBF mov bl, 5Ah ; 'Z'
F000:1BC1 cmp ah, 37h ; '7'
F000:1BC4 jz short run_test_67
F000:1BC6 jmp locret
F000:1BC9 word_F1BC9 dw 36Bh, 2 ; DATA XREF: int_89_diag_joystick+99o
F000:1BCD word_F1BCD dw 28h, 12h, 46h, 25h, 6Dh, 3Ch, 8Dh, 4Fh
F000:1BCD ; DATA XREF: int_89_diag_joystick+4Bo
F000:1BDD error_and_exit0: ; CODE XREF: int_89_diag_joystick+4j
F000:1BDD call diag_joy_err_msg
F000:1BE0 iret
F000:1BE1 error_and_exit1: ; CODE XREF: int_89_diag_joystick+9j
F000:1BE1 call diag_joy_err_msg
F000:1BE4 mov bp, offset byte_F1DFA
F000:1BE7 int 82h ; reserved for BASIC
F000:1BE9 iret
F000:1BEA run_test_e: ; CODE XREF: int_89_diag_joystick+13j
F000:1BEA ; int_89_diag_joystick+18j
F000:1BEA push cs
F000:1BEB pop ds ; ds = cs
F000:1BEC xor bx, bx
F000:1BEE mov ah, 1 ; wait for joy 1, horizontal movement
F000:1BF0 mov si, offset word_F1BCD
F000:1BF3 l3: ; CODE XREF: int_89_diag_joystick+5Cj
F000:1BF3 call diag_joy_wait_until_read
F000:1BF6 call sub_F1D59
F000:1BF9 add si, 4
F000:1BFC rol ah, 1 ; and then test joy1 Y, joy2 X and finally joy2 Y
F000:1BFE test ah, 10h ; tested all 4 LSB bits?
F000:1C01 jz short l3 ; no, keep testing then
F000:1C03 mov dh, bh
F000:1C05 or dh, bl
F000:1C07 jmp l20
F000:1C0A run_test_67: ; CODE XREF: int_89_diag_joystick+Ej
F000:1C0A ; int_89_diag_joystick+1Fj
F000:1C0A mov ax, 1
F000:1C0D int 10h ; - VIDEO - SET VIDEO MODE
F000:1C0D ; AL = mode
F000:1C0F push cs
F000:1C10 pop ds
F000:1C11 mov ah, 1
F000:1C13 mov ch, 20h ; ' '
F000:1C15 ; CH bits 0-4 = start line for cursor in character cell
F000:1C15 ; bits 5-6 = blink attribute
F000:1C15 ; CL bits 0-4 = end line for cursor in character cell
F000:1C17 mov dx, 400h
F000:1C1A mov bp, offset byte_F1D85
F000:1C1D int 82h ; reserved for BASIC
F000:1C1F mov cx, 0Dh
F000:1C22 mov dx, 800h
F000:1C25 mov bp, offset byte_F1DBD
F000:1C28 l5: ; CODE XREF: int_89_diag_joystick+85j
F000:1C28 int 82h ; reserved for BASIC
F000:1C2A loop l5
F000:1C2C cmp bl, 5Ah ; 'Z'
F000:1C2F jnz short l6
F000:1C31 jmp simulate_joy_test
F000:1C34 l6: ; CODE XREF: int_89_diag_joystick+8Aj
F000:1C34 ; int_89_diag_joystick+139j
F000:1C34 mov bp, offset byte_F1DCA
F000:1C37 mov ah, 1 ; wait for joy 1, horizontal movement
F000:1C39 l7: ; CODE XREF: int_89_diag_joystick+A7j
F000:1C39 ; int_89_diag_joystick+C9j
F000:1C39 mov dl, al
F000:1C3B call diag_joy_wait_until_read
F000:1C3E mov si, offset word_F1BC9
F000:1C41 call sub_F1D59
F000:1C44 call sub_F1D22
F000:1C47 rol ah, 1
F000:1C49 test ah, 1010b
F000:1C4C jnz short l7
F000:1C4E mov dh, al
F000:1C50 add dx, 8817h
F000:1C54 test ah, 10h
F000:1C57 pushf
F000:1C58 jz short l8
F000:1C5A sub dl, 13h
F000:1C5D l8: ; CODE XREF: int_89_diag_joystick+B3j
F000:1C5D push bx
F000:1C5E cmp bh, 11h
F000:1C61 mov bl, 0Fh
F000:1C63 jnz short l9
F000:1C65 mov bl, 0
F000:1C67 l9: ; CODE XREF: int_89_diag_joystick+BEj
F000:1C67 call sub_F1D38
F000:1C6A int 82h ; reserved for BASIC
F000:1C6C pop bx
F000:1C6D popf
F000:1C6E jz short l7
F000:1C70 push bx
F000:1C71 mov dx, 201h
F000:1C74 in al, dx
F000:1C75 mov dx, 821Fh ; row=8, col=33
F000:1C78 mov bp, offset unk_F1DCD
F000:1C7B l10: ; CODE XREF: int_89_diag_joystick+EAj
F000:1C7B ; int_89_diag_joystick+EDj
F000:1C7B mov bl, 9
F000:1C7D test al, ah
F000:1C7F jnz short l11
F000:1C81 mov bl, 0 ; attrib = 0. black over black?
F000:1C83 l11: ; CODE XREF: int_89_diag_joystick+DAj
F000:1C83 int 82h ; reserved for BASIC
F000:1C85 or dh, 80h
F000:1C88 rol ah, 1
F000:1C8A jb short l12
F000:1C8C test ah, 40h
F000:1C8F jz short l10
F000:1C91 dec dx
F000:1C92 jmp short l10
F000:1C94 l12: ; CODE XREF: int_89_diag_joystick+E5j
F000:1C94 pop bx
F000:1C95 mov dx, 2A2Ah
F000:1C98 or bx, bx
F000:1C9A jz short l19
F000:1C9C test bx, 8888h
F000:1CA0 jz short l13
F000:1CA2 mov dx, 4320h
F000:1CA5 jmp short l20
F000:1CA7 l13: ; CODE XREF: int_89_diag_joystick+FBj
F000:1CA7 cmp bx, 1111h
F000:1CAB jnz short l14
F000:1CAD mov dx, 4141h
F000:1CB0 jmp short l20
F000:1CB2 l14: ; CODE XREF: int_89_diag_joystick+106j
F000:1CB2 cmp bl, 11h
F000:1CB5 jnz short l15
F000:1CB7 mov dl, 41h ; 'A'
F000:1CB9 and bl, 0CCh
F000:1CBC l15: ; CODE XREF: int_89_diag_joystick+110j
F000:1CBC cmp bh, 11h