LS-DOS 6.3.1 - LOWCORE Assembly Listing (HTML format version)
[Copyright 1999,2002 Frank Durda IV, All Rights Reserved.
Mirroring of any material on this page in any form is expressly prohibited.
The official web site for this material is: http://nemesis.lonestar.org
Contact this address for use clearances: clearance at nemesis.lonestar.org
Comments and queries to this address: web_software at nemesis.lonestar.org]
MISOSYS EDAS-4.3 04/11/99 19:02:04 LOWCORE - LS-DOS 6.2 Page 00001
00001 ;LOWCORE/ASM - Low Memory Assignments
0000 00003 @MOD2 EQU 00 ;Set MOD2 false
FFFF 00004 @MOD4 EQU -1 ;Set MOD4 true
0000 00005 *GET BUILDVER/ASM:3
00006 ;
00007 ; Buildver/asm is a bit of a kludge since not all utilities can load
00008 ; equates from LDOS60 and still compile. LOWCORE and everybody else
00009 ; relies on this setting, and it eventually ends up in LDOS60/EQU
00010 ; for programs that can use that.
00011 ;
FFFF 00012 @BLD631 EQU -1 ;<631>Build 631 distribution (LEVEL 1B)
00013 ; These switches activate patches made since the 1B release.
00014 ; It is important that all earlier patches be enabled when a higher
00015 ; patch is enabled.
00016 ; Patches C thru F were published in TMQ IV.iv, page 32 (NOTE: the
00017 ; patch addresses listed for SPOOL in SPOOL1/FIX are 19H high.)
FFFF 00018 @BLD631C EQU -1 ;<631>Apply 1C patches (SETKI)
FFFF 00019 @BLD631D EQU -1 ;<631>Apply 1D patches (DIR)
FFFF 00020 @BLD631E EQU -1 ;<631>Apply 1E patches (DIR & MEMDISK/DCT)
FFFF 00021 @BLD631F EQU -1 ;<631>Apply 1F patches (SPOOL)
00022 ; Patches G and H were published in TMQ V.i, pages 10 and 18/19.
FFFF 00023 @BLD631G EQU -1 ;<631>Apply 1G patches (//KEYIN,DIR,DO *)
FFFF 00024 @BLD631H EQU -1 ;<631>Apply 1H patches (MEMORY)
00025 ;
00026 ;End of BUILDVER/ASM
00027 ;
00028 ; LDOS 6.x Low Core RAM storage assignments
00029 ; Copyright (C) 1982 by Logical Systems, Inc.
00030 ;
00031 ; Define switches for international or domestic
00032 ;
0000 00033 @GERMAN EQU 0
0000 00034 @FRENCH EQU 0
00035 IF @GERMAN.AND.@FRENCH
00036 ERR 'Can''t do both French and German'
00037 ENDIF
00038 IF @GERMAN.OR.@FRENCH
00039 @INTL EQU -1
00040 @USA EQU 00
00041 @HZ50 EQU -1
00042 ELSE
0000 00043 @INTL EQU 00
FFFF 00044 @USA EQU -1
0000 00045 @HZ50 EQU 00
00046 ENDIF
00047 ;
0000 00048 START$ EQU 0
00049 ;
00050 ; These EQUs are detailed in SYSRES
00051 ;
000E 00052 FDDINT$ EQU 0EH
001B 00053 PDRV$ EQU 1BH
002B 00054 TIMSL$ EQU 2BH
002C 00055 TIMER$ EQU 2CH
002D 00056 TIME$ EQU TIMER$+1
0033 00057 DATE$ EQU 33H
003E 00058 INTVC$ EQU 3EH
006A 00059 FLGTAB$ EQU 6AH
006C 00060 CFLAG$ EQU FLGTAB$+'C'-'A'
006D 00061 DFLAG$ EQU FLGTAB$+'D'-'A'
0072 00062 IFLAG$ EQU FLGTAB$+'I'-'A'
0074 00063 KFLAG$ EQU FLGTAB$+'K'-'A'
0076 00064 MODOUT$ EQU FLGTAB$+'M'-'A'
0077 00065 NFLAG$ EQU FLGTAB$+'N'-'A'
0078 00066 OPREG$ EQU FLGTAB$+'O'-'A'
007B 00067 RFLAG$ EQU FLGTAB$+'R'-'A'
007C 00068 SFLAG$ EQU FLGTAB$+'S'-'A'
007F 00069 VFLAG$ EQU FLGTAB$+'V'-'A'
0089 00070 @KITSK EQU FLGTAB$+31
00071 ;
0200 00072 ORG 200H+START$
00073 ;
00074 ; Page 2 - Device Control Blocks
00075 ;
0200 00 00076 BUR$ DB 00H ;Bank use RAM
0201 FE 00077 BAR$ DB 0FEH ;Bank available RAM
0202 14 00078 LBANK$ DB 20 ;Dir cyl & logical bank
0203 01 00079 JCLCB$ DB 1,0,0 ;Mini-DCB for JCL gets
00 00
0206 F40F 00080 DVRHI$ DW DVREND$ ;Start of low I/O zone
0208 05 00081 KIDCB$ DB 5 ;Permit CTL, GET
0209 F008 00082 DW KIDVR
020B 00 00083 DB 0,0,0,'KI'
00 00 4B 49
0210 07 00084 DODCB$ DB 7 ;Permit CTL, PUT, GET
0211 880B 00085 DW DODVR
0213 00 00086 DB 0,0,0,'DO'
00 00 44 4F
0218 06 00087 PRDCB$ DB 6 ;Permit CTL, PUT
0219 010E 00088 DW PRDVR
021B 00 00089 DB 0,0,0,'PR'
00 00 50 52
0220 15 00090 SIDCB$ DB 15H ;Routed to *KI
0221 0802 00091 DW KIDCB$
0223 0D 00092 DB 0DH,0,0,'SI'
00 00 53 49
0228 17 00093 SODCB$ DB 17H ;Routed to *DO
0229 1002 00094 DW DODCB$
022B 0F 00095 DB 0FH,0,0,'SO'
00 00 53 4F
0230 0A 00096 JLDCB$ DB 0AH,0,0,0AH,0,0,'JL'
00 00 0A 00 00 4A 4C
0238 00097 S1DCB$ EQU $ ;1st spare DCB
0031 00098 DCBKL$ EQU JLDCB$&0FFH+1 ;Non-killable DCB's
00099 ;
00100 ; Now load the BOOT loader - part in this page
00101 ;
0238 00102 *GET BOOT4:3
00103 ;BOOT4/ASM - LS-DOS 6.3
00104 ; SUBTTL ''
00106 *MOD
00107 ;
0040 00108 KEYIN EQU 40H
0066 00109 NMIVECT EQU 66H
021B 00110 DSPLY EQU 21BH
1200 00111 BUFFER EQU 1200H
43F6 00112 BOOTBUF EQU 43FFH-9
00113 ;
00114 ; Boot loader routine read in by ROM, along with
00115 ; the lowcore I/O drivers.
00116 ; This section loads in SYSRES
00117 ;
0238 FD217004 00118 LBOOT LD IY,DCT$ ;Set IY for FDCDVR use
023C FD7E09 00119 LD A,(IY+9) ;Directory track is
023F FD7705 00120 LD (IY+5),A ; the current track
0242 3E04 00121 LD A,4
0244 327B00 00122 LD (FLGTAB$+'R'-'A'),A ;Set retries
0247 3EC9 00123 LD A,0C9H
0249 320E00 00124 LD (FDDINT$),A ;Return for disk driver
024C 3E12 00125 LD A,18 ;5" sectors/track, dden
024E FDCB046E 00126 BIT 5,(IY+4) ;Dbl sided?
0252 2801 00127 JR Z,NOTDBL
0254 87 00128 ADD A,A ;Adjust to 36 sect/cyl
0255 32A502 00129 NOTDBL LD (SECTRK),A
00130 ;
00131 ; Set up for a fragmented file
00132 ;
0258 D9 00133 EXX
0259 0E06 00134 LD C,6 ;Sectors/gran
025B CDB102 00135 CALL GETEXT ;Pick up extent 1
025E D9 00136 EXX
00137 ;
025F CD6802 00138 CALL LOAD ;Read in sysres
0262 3EFB 00139 LD A,0FBH ;EI instruction
0264 32950F 00140 LD (DISKEI),A ; stuffed into FDCDVR
0267 E9 00141 JP (HL) ;Continue system init
00142 ;
0268 CD9702 00143 LOAD CALL RDBYTE ;Get type code
026B 3D 00144 DEC A
026C 200C 00145 JR NZ,LOAD2 ;Bypass if not type 1
026E CD8802 00146 CALL GETADR ;Get blk len & load adr
0271 CD9702 00147 LOAD1 CALL RDBYTE ;Start reading the block
0274 77 00148 LD (HL),A ;Stuff into memory
0275 23 00149 INC HL ;Bump memory pointer
0276 10F9 00150 DJNZ LOAD1 ;Loop for entire block
0278 18EE 00151 JR LOAD ;Restart the process
00152 ;
027A 3D 00153 LOAD2 DEC A ;Test if type 2 (traadr)
027B 280B 00154 JR Z,GETADR ;Ah, go if transfer addr
027D CD9702 00155 CALL RDBYTE ;Assume comment,
0280 47 00156 LD B,A ; get comment length
0281 CD9702 00157 LOAD3 CALL RDBYTE ; & ignore it
0284 10FB 00158 DJNZ LOAD3
0286 18E0 00159 JR LOAD ;Continue to read
00160 ;
00161 ; got the transfer address type code
00162 ;
0288 CD9702 00163 GETADR CALL RDBYTE ;Get block length
028B 47 00164 LD B,A
028C CD9702 00165 CALL RDBYTE ;Get lo-order load addr
028F 6F 00166 LD L,A
0290 05 00167 DEC B ;Adj length for this byte
0291 CD9702 00168 CALL RDBYTE ;Get hi-order load addr
0294 67 00169 LD H,A
0295 05 00170 DEC B ;Adj length for this byte
0296 C9 00171 RET
00172 ;
00173 ; routine to read a byte
00174 ;
0297 D9 00175 RDBYTE EXX ;Switch memory/buf ptrs
0298 2C 00176 INC L ;Bump buf pointer
0299 2013 00177 JR NZ,RDB2 ;Bypass disk i/o if more
029B C5 00178 PUSH BC
029C 0609 00179 LD B,9 ;Read sector function #
029E CD7004 00180 CALL DCT$ ;Get another sector
02A1 C1 00181 POP BC
02A2 1C 00182 INC E ;Bump sector counter
02A3 7B 00183 LD A,E
02A4 D600 00184 SUB $-$ ;Is this the last sector
02A5 00185 SECTRK EQU $-1
02A6 2002 00186 JR NZ,RDB1 ; on the cylinder?
02A8 5F 00187 LD E,A ;Yes, restart at 0
02A9 14 00188 INC D ; & bump the cylinder up
02AA 05 00189 RDB1 DEC B ;Dec sectors this extent
02AB CCB102 00190 CALL Z,GETEXT ;Get next extent if 0
02AE 7E 00191 RDB2 LD A,(HL) ;P/u a byte
02AF D9 00192 EXX ;Exc mem/buf pointers
02B0 C9 00193 RET
00194 ;
00195 ; Load DE track,sector, B sectors this extent
00196 ;
00197 GETEXT
02B1 DD23 00198 INC IX ;Index directory entry
02B3 DD23 00199 INC IX ;Pt at grans this ext.
02B5 DD7E00 00200 LD A,(IX)
02B8 F5 00201 PUSH AF ;Save for later
02B9 07 00202 RLCA
02BA 07 00203 RLCA ;Normalize start gran
02BB 07 00204 RLCA
02BC E607 00205 AND 7
02BE CDCE02 00206 CALL MULTCA ;Start gran * grans/sec
02C1 5F 00207 LD E,A ;This is start sector
02C2 F1 00208 POP AF
02C3 E61F 00209 AND 00011111B ;Get total grans
02C5 3C 00210 INC A ; this extent
02C6 CDCE02 00211 CALL MULTCA ; * sect/gran
02C9 47 00212 LD B,A ;Sectors this extent
02CA DD56FF 00213 LD D,(IX-1) ;Cyl this extent
02CD C9 00214 RET
00215 ;
00216 ; Short multiply C * A
00217 ;
02CE C5 00218 MULTCA PUSH BC ;Save sect/gran in C
02CF 57 00219 LD D,A
02D0 AF 00220 XOR A
02D1 0608 00221 LD B,8
02D3 87 00222 MLTCA ADD A,A
02D4 CB21 00223 SLA C
02D6 3001 00224 JR NC,MLTCA1
02D8 82 00225 ADD A,D
02D9 10F8 00226 MLTCA1 DJNZ MLTCA
02DB C1 00227 POP BC
02DC C9 00228 RET
00229 ;
00230 ; Initialize the CRTC
00231 ;
00232 INITCRTC
02DD 01880F 00233 LD BC,15<8!88H ;Count, CRTC address reg
02E0 21FD02 00234 LD HL,CRTCTAB
02E3 7E 00235 $A1 LD A,(HL)
02E4 ED41 00236 OUT (C),B ;Pass reg # to CRTC
02E6 D389 00237 OUT (89H),A ;Pass value to CRTC reg
02E8 2B 00238 DEC HL ;Backup to next value
02E9 05 00239 DEC B ;To next lower reg
02EA F2E302 00240 JP P,$A1
02ED C9 00241 RET
02EE 63 00242 DB 99 ;Horiz total MD
02EF 50 00243 DB 80 ;Horiz displayed MD
02F0 55 00244 DB 85 ;Horiz sync position MD
02F1 0A 00245 DB 10 ;Horiz sync width
02F2 19 00246 DB 25 ;Vertical total
02F3 04 00247 DB 4 ;Vertical total adjust
02F4 18 00248 DB 24 ;Vertical displayed
02F5 18 00249 DB 24 ;Vertical sync position
02F6 00 00250 DB 0 ;Interlace mode
02F7 09 00251 DB 9 ;Maximum scan line addr
02F8 65 00252 DB 65H ;Cursor start
02F9 09 00253 DB 9 ;Cursor end
02FA 00 00254 DB 0 ;Start address (H)
02FB 00 00255 DB 0 ;Start address (L)
02FC 00 00256 DB 0 ;Cursor (H)
02FD 00 00257 CRTCTAB DB 0 ;Cursor (L)
02FE 00 00258 DC -$&0FFH,0
00
00259 ;
00260 ; System BOOT entry point, loaded by ROM
00261 ;
0300 00262 CORE$ DEFL $
4300 00263 ORG 4300H
4300 00 00264 BOOT NOP
4301 FE14 00265 CP 14H ;Directory track location
4302 00266 DIRTRK EQU $-1
4303 F3 00267 DI
4304 3E86 00268 LD A,86H ;Bring up the RAM
4306 D384 00269 OUT (@OPREG),A
4308 327800 00270 LD (OPREG$),A
430B 2100F8 00271 LD HL,CRTBGN$ ;Clear video RAM
430E 1101F8 00272 LD DE,CRTBGN$+1
4311 017F07 00273 LD BC,CRTSIZE-1
4314 3620 00274 LD (HL),' '
4316 EDB0 00275 LDIR
4318 21CD43 00276 LD HL,NMIRET ;Set NMI vector
431B 226700 00277 LD (NMIVECT+1),HL
431E 3EC3 00278 LD A,0C3H
4320 326600 00279 LD (NMIVECT),A
4323 3EC9 00280 LD A,0C9H ;Stuff return for ints
4325 323800 00281 LD (38H),A
00282 ;
00283 ; Read the first 16 sectors of track 0
00284 ;
4328 210002 00285 LD HL,START$+200H ;Pt to page 2
432B 55 00286 LD D,L ;Init to track 0, sec 0
432C 5D 00287 LD E,L
432D CD7743 00288 RDBOOT CALL RDSEQ ;Read a sector
4330 24 00289 INC H ;Bump to next page
4331 1C 00290 INC E ;Bump to next
4332 3E10 00291 LD A,16
4334 BB 00292 CP E ;Loop if more
4335 20F6 00293 JR NZ,RDBOOT
4337 CDDD02 00294 CALL INITCRTC ;Initialize the CRTC
00295 ;
00296 ; Now set up to load SYSRES
00297 ;
433A 3A0243 00298 LD A,(DIRTRK) ;P/u dir cyl
433D 327904 00299 LD (DCT$+9),A ;Update DCT to show DIR
4340 57 00300 LD D,A ;Set starting track and
4341 1E00 00301 LD E,0 ; init to read the GAT
4343 CD7443 00302 CALL RDSECT ; into BUFFER
4346 3ACD12 00303 LD A,(BUFFER+0CDH) ;Update DCT$ to show
4349 E620 00304 AND 20H ; the # of sides
434B 217404 00305 LD HL,DCT$+4
434E B6 00306 OR (HL)
434F 77 00307 LD (HL),A
4350 1E04 00308 LD E,4 ;Pt to SYS0 dir sector
4352 CD7443 00309 CALL RDSECT ;Read the SYS0 dir sec
4355 3A0012 00310 LD A,(BUFFER) ;Test if system disk
4358 E610 00311 AND 10H
435A 282D 00312 JR Z,NOTSYS ;Go if not
435C 211D12 00313 LD HL,BUFFER+21+8 ;SYS0 extent info
435F 11F643 00314 LD DE,BOOTBUF ;Use 43FF-8
4362 010800 00315 LD BC,8
4365 EDB8 00316 LDDR ;Store 1st four extents
4367 D5 00317 PUSH DE ;Pt IX to 1 byte
4368 DDE1 00318 POP IX ; before extent info
436A D9 00319 EXX
436B 21FF12 00320 LD HL,BUFFER+255 ;Init to buffer end
436E D9 00321 EXX
436F C33802 00322 JP LBOOT ;Load SYSRES
4372 00 00323 DB 0,0 ;Padding for posn
00
00324 ;
00325 ; routine to read a sector
00326 ;
4374 210012 00327 RDSECT LD HL,BUFFER ;Set buffer
4377 0605 00328 RDSEQ LD B,5 ;Init retry counter
4379 C5 00329 RDS1 PUSH BC ;Save counter
437A E5 00330 PUSH HL ;Save for retries
437B CD9643 00331 CALL READ ;Attempt read
437E E1 00332 POP HL
437F C1 00333 POP BC
4380 E61C 00334 AND 1CH ;Mask status
4382 C8 00335 RET Z ;Return if no error
4383 10F4 00336 DJNZ RDS1 ;Loop for retry
4385 21E043 00337 GOTERR LD HL,DISKERR ;"Disk error"
4388 DD 00338 DB 0DDH ;Hide next instruction
4389 21EA43 00339 NOTSYS LD HL,NOSYS ;"No system"
438C 010A00 00340 LD BC,ERRLEN
438F 1193FB 00341 LD DE,80*11+CRTBGN$+35 ;Middle of screen
4392 EDB0 00342 LDIR
4394 18FE 00343 HALTS JR HALTS ;Wait for RESET
00344 ;
4396 01F481 00345 READ LD BC,81F4H ;Set DDEN, DS1, d.s. port
4399 ED41 00346 OUT (C),B ;Select it
439B 0D 00347 DEC C ;Point C to data reg
439C 3E18 00348 LD A,18H ;Seek command (6 ms)
439D 00349 BOOTST$ EQU $-1 ;Set for boot step rate
00350 IFNE BOOTST$,439DH
00351 ERR 'Boot step out of position'
00352 ENDIF
439E ED51 00353 OUT (C),D ;Set desired track
43A0 CDD943 00354 CALL FDCMD ;Pass command & delay
43A3 DBF0 00355 SEEK1 IN A,(0F0H) ;Get status
43A5 CB47 00356 BIT 0,A ;Busy?
43A7 20FA 00357 JR NZ,SEEK1
43A9 7B 00358 LD A,E ;Set sector register
43AA D3F2 00359 OUT (0F2H),A
43AC 3E81 00360 LD A,81H ;Set DDEN & DS1
43AE D3F4 00361 OUT (0F4H),A
43B0 D5 00362 PUSH DE
43B1 1102C1 00363 LD DE,81H!40H<8!2 ;D=DS1 + DDEN + WSGEN
00364 ;E=Mask to see DRQ
43B4 3E80 00365 LD A,80H ;FDC READ command
43B6 CDD943 00366 CALL FDCMD ;Pass to ctrlr & set B=0
43B9 3EC0 00367 LD A,0C0H ;Enable INTRQ & timeout
43BB D3E4 00368 OUT (0E4H),A
43BD DBF0 00369 READLP1 IN A,(0F0H) ;Grab status
43BF A3 00370 AND E ;Test bit 1
43C0 28FB 00371 JR Z,READLP1
43C2 EDA2 00372 INI
43C4 7A 00373 LD A,D ;Set DDEN & DS1 & WSGEN
43C5 D3F4 00374 READLP2 OUT (0F4H),A ;Continue to select
43C7 EDA2 00375 INI ; while inputting
43C9 20FA 00376 JR NZ,READLP2
43CB 18FE 00377 JR $ ;Wait for NMI
43CD D1 00378 NMIRET POP DE ;Pop interrupt ret
43CE D1 00379 POP DE ;Restore DE
43CF AF 00380 XOR A ;Disable INTRQ & timeout
43D0 D3E4 00381 OUT (0E4H),A
43D2 3E81 00382 LD A,81H ;Reselect drive
43D4 D3F4 00383 OUT (0F4H),A
43D6 DBF0 00384 IN A,(0F0H) ;Get status
43D8 C9 00385 RET
43D9 D3F0 00386 FDCMD OUT (0F0H),A ;Give cmd to ctrlr
43DB 0618 00387 LD B,24 ;Time delay
43DD 10FE 00388 DJNZ $
43DF C9 00389 RET
43E0 44 00390 DISKERR DB 'Disk error'
69 73 6B 20 65 72 72 6F
72
43EA 4E 00391 NOSYS DB 'No system '
6F 20 73 79 73 74 65 6D
20
000A 00392 ERRLEN EQU $-NOSYS ;Length of error msg
43F4 00 00393 DC -$&0FFH,0
00 00 00 00 00 00 00 00
00 00 00
0400 00394 ORG CORE$+256
00396 ;
00399 ;
00400 ; Page 3 - System stack and Sysinfo section
00401 ;
0380 00402 STACK$ EQU $-128 ;Start stack 128 bytes low
0382 00403 PAUSE@ EQU STACK$+2 ;Where pause will be
00404 ;
00405 ; Page 4 - Miscellaneous stuff
00406 ;
0400 63 00407 DB 63H ;Operating system version
0401 C9 00408 ZERO$ DB 0C9H ;Config on BOOT, yes = 0
0401 00409 MAXDAY$ EQU $-1 ;Max days per month
0402 1F 00410 DB 31,28,31,30,31,30,31,31,30,31,30,31
1C 1F 1E 1F 1E 1F 1F 1E
1F 1E 1F
040E 00 00411 HIGH$ DS 2 ;Highest available memory
00
0410 4C 00412 PAKNAM$ DB 'LS-DOS63Level-';<631>
53 2D 44 4F 53 36 33 4C
65 76 65 6C 2D
041E 31 00413 DB '1' ;<631>
00414 IF @BLD631H
041F 48 00415 DB 'H' ;<631H>Level-1H
00416 ELSE
00417 IF @BLD631G
00418 DB 'G' ;<631G>Level-1G
00419 ELSE
00420 IF @BLD631F
00421 DB 'F' ;<631F>Level-1F
00422 ELSE
00423 IF @BLD631E
00424 DB 'E' ;<631E>Level-1E
00425 ELSE
00426 IF @BLD631D
00427 DB 'D' ;<631D>Level-1D
00428 ELSE
00429 IF @BLD631C
00430 DB 'C' ;<631C>Level-1C
00431 ELSE
00432 DB 'B' ;<631>Level-1B (tree base)
00433 ENDIF ;C
00434 ENDIF ;D
00435 ENDIF ;E
00436 ENDIF ;F
00437 ENDIF ;G
00438 ENDIF ;H
00439 ;
00440 ; Command line input buffer & AUTO buffer area
00441 ;
0420 0D 00442 INBUF$ DB 0DH ;Input buffer - 80 bytes
0421 00 00443 DC 79,0
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00
00444 ;
00445 ; System drive code tables
00446 ;
0470 00447 DCT$ EQU $ ;System drive code tables
0470 C33D0E 00448 JP FDCDVR ;Floppy drive 0
0473 44 00449 DB 44H,0C1H,0,27H,17,3-1<5+6-1,20
C1 00 27 11 45 14
047A C33D0E 00450 JP FDCDVR ;Floppy drive 1
047D 44 00451 DB 44H,42H,-1,27H,17,3-1<5+6-1,20
42 FF 27 11 45 14
0484 C9 00452 RET ;Disable drive #2
0485 3D0E 00453 DW FDCDVR
0487 44 00454 DB 44H,44H,-1,27H,17,3-1<5+6-1,20
44 FF 27 11 45 14
048E C9 00455 RET ;Disable drive #3
048F 3D0E 00456 DW FDCDVR
0491 44 00457 DB 44H,48H,-1,27H,17,3-1<5+6-1,20
48 FF 27 11 45 14
0498 C9 00458 RET ;Logical drive 4
0499 2A0F 00459 DW FDCRET
049B 00 00460 DB 0,0,0,27H,0,0,0
00 00 27 00 00 00
04A2 C9 00461 RET ;Logical drive 5
04A3 2A0F 00462 DW FDCRET
04A5 00 00463 DB 0,0,0,27H,0,0,0
00 00 27 00 00 00
04AC C9 00464 RET ;Logical drive 6
04AD 2A0F 00465 DW FDCRET
04AF 00 00466 DB 0,0,0,27H,0,0,0
00 00 27 00 00 00
04B6 C9 00467 RET ;Logical drive 7
04B7 2A0F 00468 DW FDCRET
04B9 00 00469 DB 0,0,0,27H,0,0,0
00 00 27 00 00 00
00470 ;
00471 ; SYSINFO - miscellaneous information
00472 ;
04C0 FF 00473 DSKTYP$ DB -1 ;0 = DATA, <> 0 = SYS
04C1 00 00474 DB 0 ;Reserved
04C2 00 00475 DTPMT$ DB 0 ;Date prompt at boot
04C3 00 00476 TMPMT$ DB 0 ;Time prompt at boot
04C4 00 00477 RSTOR$ DB 0 ;Suppress restores on BOOT
04C5 00 00478 DS 2 ;Reserved
00
04C7 53 00479 DAYTBL$ DB 'SunMonTueWedThuFriSat'
75 6E 4D 6F 6E 54 75 65
57 65 64 54 68 75 46 72
69 53 61 74
04DC 4A 00480 MONTBL$ DB 'JanFebMarAprMayJunJulAugSepOctNovDec'
61 6E 46 65 62 4D 61 72
41 70 72 4D 61 79 4A 75
6E 4A 75 6C 41 75 67 53
65 70 4F 63 74 4E 6F 76
44 65 63
00481 ;
00482 ; End of low core assignments
00483 ;
0500 00484 *GET IODVR:3 ;I/O driver, KEYIN, etc.
00485 ;IODVR/ASM - LS-DOS 6.2
00488 ;
001C 00489 HOME EQU 1CH
001F 00490 CLRFRM EQU 1FH
00491 ;
00492 ; Log out routine - display & log
00493 ;
0500 CD2D05 00494 @LOGOT CALL @DSPLY
00495 ;
00496 ; Job log loger routine
00497 ;
0503 3A3002 00498 @LOGER LD A,(JLDCB$) ;If NIL, don't do
0506 EE08 00499 XOR 8 ; anything
0508 E608 00500 AND 8
050A C8 00501 RET Z
050B E5 00502 PUSH HL ;Save pointer to command
050C 211D05 00503 LD HL,LOGBUF ;Get time string into buf
050F E5 00504 PUSH HL
0510 CD8D07 00505 CALL @TIME
0513 E1 00506 POP HL
0514 113002 00507 LD DE,JLDCB$ ;Log the time
0517 CD3005 00508 CALL @MSG
051A E1 00509 POP HL ;Log the command
051B 1813 00510 JR @MSG
051D 68 00511 LOGBUF DB 'hh:mm:ss ',3
68 3A 6D 6D 3A 73 73 20
20 03
00512 ;
00513 ; Line print routine
00514 ;
0528 111802 00515 @PRINT LD DE,PRDCB$ ;Printer DCB
052B 1803 00516 JR @MSG
00517 ;
00518 ; Line display routine
00519 ;
052D 111002 00520 @DSPLY LD DE,DODCB$ ;Video DCB
00521 ;
00522 ; Device message routine
00523 ;
00524 *MOD
0530 E5 00525 @MSG PUSH HL ;Save pointer to message
0531 7E 00526 $B1 LD A,(HL) ;P/u a message character
0532 FE03 00527 CP 3 ;Exit on ETX
0534 280D 00528 JR Z,$B3
0536 FE0D 00529 CP CR ;Exit & put on ENTER
0538 2806 00530 JR Z,$B2
053A C44506 00531 CALL NZ,@PUT ;Else put the char
053D 23 00532 INC HL ; & loop on no error
053E 28F1 00533 JR Z,$B1 ; else fall thru & exit
0540 CC4506 00534 $B2 CALL Z,@PUT
0543 E1 00535 $B3 POP HL
0544 C9 00536 RET
00537 ;
00538 ; Clear screen routine
00539 ;
0545 3E1C 00540 @CLS LD A,HOME ;Cursor home to 0,0
0547 CD4D05 00541 CALL DSPBYT
054A C0 00542 RET NZ ;Return on error
054B 3E1F 00543 LD A,CLRFRM ;Clear to end of frame
054D D5 00544 DSPBYT PUSH DE
054E CD4206 00545 CALL @DSP
0551 D1 00546 POP DE
0552 C9 00547 RET
00548 ;
00549 ; Check and Clear bit SVC
00550 ;
00551 @CKBRKC
0553 E5 00552 PUSH HL ;Save registers
0554 217400 00553 LD HL,KFLAG$ ;Point to KFLAG$
0557 CB46 00554 BIT 0,(HL) ;Check break bit
0559 281A 00555 JR Z,NOBRK ; and ret if none
055B F5 00556 PUSH AF ;Save flags
055C C5 00557 PUSH BC
055D D5 00558 PUSH DE
055E CB86 00559 BRKTEST RES 0,(HL) ;Reset the break bit
0560 01000B 00560 LD BC,0B00H ;Wait more than 1/30
0563 CD8203 00561 CALL PAUSE@ ; of a second
0566 CB46 00562 BIT 0,(HL) ;Test the bit again
0568 20F4 00563 JR NZ,BRKTEST ;Loop until gone
056A 110802 00564 LD DE,KIDCB$ ;Point at keyboard &
056D 3E03 00565 LD A,03 ; clear buffer with
056F CD2306 00566 CALL @CTL ; control 3 call
0572 D1 00567 POP DE
0573 C1 00568 POP BC ;Recover registers
0574 F1 00569 POP AF ;Recover FLAGS
0575 E1 00570 NOBRK POP HL
0576 C9 00571 RET
00572 ;
00573 ; Keyboard line input routine
00574 ;
00575 *MOD
00576 ;
00577 ; Backspace to beginning of line
00578 ;
0577 CDDB05 00579 $C4 CALL $C6 ;Backspace
057A 2B 00580 DEC HL ;Get the char prior
057B 7E 00581 LD A,(HL) ; to the current
057C 23 00582 INC HL
057D FE0A 00583 CP 0AH ;Return if line feed
057F C8 00584 RET Z
0580 78 00585 $C5 LD A,B ;Check for empty buffer
0581 B9 00586 CP C
0582 20F3 00587 JR NZ,$C4 ;Loop if not
0584 C9 00588 RET ; else return
0585 E5 00589 @KEYIN PUSH HL ;Save buffer pointer
0586 48 00590 LD C,B ;Set C = buffer size
0587 112806 00591 $C1 LD DE,@KEY ;Init for standard input
058A 3A7C00 00592 LD A,(SFLAG$) ;If JCL is active,
058D E620 00593 AND 20H ; then use the JCL input
058F 2802 00594 JR Z,$C0 ;Must loop here in case
0591 1E30 00595 LD E,@JCL&0FFH ; JCL exits with //STOP
0593 ED539805 00596 $C0 LD ($C1A+1),DE
0597 CD0000 00597 $C1A CALL $-$ ;Get a key
059A 203D 00598 JR NZ,$C3B ;Back on error
059C FE80 00599 CP 80H ;Break?
059E 2875 00600 JR Z,$C10
05A0 FE20 00601 CP 20H ;Go if not a control
05A2 3020 00602 JR NC,$C2
05A4 FE0D 00603 CP 0DH ;Carriage return?
05A6 286E 00604 JR Z,$C11
05A8 FE1F 00605 CP 1FH ;Clear?
05AA 2825 00606 JR Z,$C3
05AC 118705 00607 LD DE,$C1 ;Set return address
05AF D5 00608 PUSH DE
05B0 FE08 00609 CP 08H ;Backspace?
05B2 2827 00610 JR Z,$C6
05B4 FE18 00611 CP 18H ;Backspace to BOL?
05B6 28C8 00612 JR Z,$C5
05B8 FE09 00613 CP 09H ;Tab?
05BA 283C 00614 JR Z,$C8
05BC FE12 00615 CP 'R'&1FH ;CTL-R?
05BE 282A 00616 JR Z,$C7
05C0 FE0A 00617 CP 0AH ;Line feed?
05C2 C0 00618 RET NZ ;Ret if none above
05C3 D1 00619 POP DE ;Pop the return
05C4 77 00620 $C2 LD (HL),A ;Stuff the char
05C5 78 00621 LD A,B ;Check on buffer full
05C6 B7 00622 OR A
05C7 28BE 00623 JR Z,$C1 ;Loop if so
05C9 7E 00624 LD A,(HL) ; else get char
05CA 23 00625 INC HL ; & bump pointer
05CB 05 00626 DEC B ;Count down
05CC CD4206 00627 CALL @DSP ;Display entry
05CF 1806 00628 JR $C3A ; then loop
00629 ;
00630 ; Clear the screen invoked
00631 ;
05D1 CD4505 00632 $C3 CALL @CLS
05D4 41 00633 LD B,C ;Reset to start of
05D5 E1 00634 POP HL ; line & start of
05D6 E5 00635 PUSH HL ; buffer
05D7 28AE 00636 $C3A JR Z,$C1
05D9 183B 00637 $C3B JR $C11
00638 ;
00639 ; Backspace key entry
00640 ;
05DB 78 00641 $C6 LD A,B ;If buffer is empty,
05DC B9 00642 CP C ; return
05DD C8 00643 RET Z
05DE 2B 00644 DEC HL ; else do the backspace
05DF 7E 00645 LD A,(HL)
05E0 FE0A 00646 CP 0AH ;Last char a linefeed?
05E2 23 00647 INC HL
05E3 C8 00648 RET Z ;Return if so
05E4 2B 00649 DEC HL
05E5 04 00650 INC B ;Add back one char
05E6 3E08 00651 LD A,8 ;Backspace the cursor
05E8 1858 00652 JR @DSP
00653 ;
00654 ; Test if repeat last command
00655 ;
05EA 3A6C00 00656 $C7 LD A,(CFLAG$) ;Test if SYS1 KEYIN bit
05ED E604 00657 AND 4 ; is set (bit 2)
05EF C8 00658 RET Z ;Ignore CTL if not
05F0 78 00659 LD A,B ;If not at 1st position,
05F1 B9 00660 CP C ; don't permit it
05F2 C0 00661 RET NZ
05F3 E1 00662 POP HL ;Pop return to KEY
05F4 E1 00663 POP HL ;Point to command buffer
05F5 C32D05 00664 JP @DSPLY ;Display the old command
00665 ;
00666 ; Tab entered
00667 ;
05F8 E5 00668 $C8 PUSH HL ;Get pos on line
05F9 CDF10D 00669 CALL ADDR_2_ROWCOL ;Get row,col in HL
05FC 7D 00670 LD A,L ;Xfer column to A
05FD E1 00671 POP HL
05FE E607 00672 AND 7
0600 ED44 00673 NEG ;Negate and add tab
0602 C608 00674 ADD A,8
0604 5F 00675 LD E,A ;Reg E has tab length
0605 78 00676 $C9 LD A,B ;Check on buffer full
0606 B7 00677 OR A
0607 C8 00678 RET Z
0608 3E20 00679 LD A,' ' ;Put spaces until
060A 77 00680 LD (HL),A ; tab expanded
060B 23 00681 INC HL
060C CD4D05 00682 CALL DSPBYT
060F C0 00683 RET NZ
0610 05 00684 DEC B ;Dec buffer remaining
0611 1D 00685 DEC E ;Dec tab count
0612 C8 00686 RET Z
0613 18F0 00687 JR $C9
00688 ;
00689 ; Exit KEYIN routine
00690 ;
0615 37 00691 $C10 SCF ;BREAK exit with CF
0616 F5 00692 $C11 PUSH AF ;Save flag
0617 3E0D 00693 LD A,0DH ;Stuff CR at end
0619 77 00694 LD (HL),A
061A CD4206 00695 CALL @DSP ; & display it
061D 79 00696 LD A,C ;Calculate # of chars
061E 90 00697 SUB B ; entered
061F 47 00698 LD B,A
0620 F1 00699 POP AF ;Rcvr flag
0621 E1 00700 POP HL ;Restore buffer ptr
0622 C9 00701 RET
00702 ;
00703 ; Byte I/O device handler
00704 ; C => character if PUT or CTL
00705 ; DE => Device control block
00706 ;
00707 *MOD
0623 C5 00708 @CTL PUSH BC
0624 0604 00709 LD B,4 ;Bit 2, CTL
0626 1820 00710 JR IOBGN
0628 CD3506 00711 @KEY CALL @KBD ;Scan the keyboard
062B C8 00712 RET Z ;Ret if key available
062C B7 00713 OR A ;Return if error
062D 28F9 00714 JR Z,@KEY
062F C9 00715 RET
0630 110302 00716 @JCL LD DE,JCLCB$ ;JCL file FCB
0633 1803 00717 JR @GET
0635 110802 00718 @KBD LD DE,KIDCB$ ;Keyboard DCB
0638 C5 00719 @GET PUSH BC
0639 0601 00720 LD B,1 ;Bit 0, GET
063B 180B 00721 JR IOBGN
063D 111802 00722 @PRT LD DE,PRDCB$ ;Printer DCB
0640 1803 00723 JR @PUT
0642 111002 00724 @DSP LD DE,DODCB$ ;Video DCB
0645 C5 00725 @PUT PUSH BC
0646 0602 00726 LD B,2 ;Bit 1, PUT
0648 DDE5 00727 IOBGN PUSH IX ;Save the registers
064A E5 00728 PUSH HL
064B D5 00729 PUSH DE ;Xfer DCB to IX
064C DDE1 00730 POP IX
064E D5 00731 PUSH DE
064F 4F 00732 LD C,A ;Xfer the I/O char
0650 218006 00733 LD HL,@RSTREG ;Restore register routine
0653 3A0202 00734 LD A,(LBANK$) ;If bank 0 is not
0656 B7 00735 OR A ; resident, need to
0657 280E 00736 JR Z,$D0 ; get it resident!
00737 ;
00738 ; Some other bank is resident - invoke bank 0
00739 ;
0659 C5 00740 PUSH BC ;Save reg again
065A AF 00741 XOR A ;Prepare for bank-0
065B 47 00742 LD B,A
065C 4F 00743 LD C,A
065D CD7708 00744 CALL @BANK ;Invoke bank-0
0660 60 00745 LD H,B ;Get old bank data
0661 69 00746 LD L,C ; into reg HL
0662 C1 00747 POP BC ;Rcvr BC
0663 E5 00748 PUSH HL ;Bank data to stack
0664 217906 00749 LD HL,RSTBNK ;Set return address
0667 E5 00750 $D0 PUSH HL ; to restore registers
0668 1A 00751 LD A,(DE) ;P/u DCB type byte
0669 B7 00752 OR A
066A C8 00753 RET Z ;Back if nothing
066B FE08 00754 CP 8 ;Ck on GET/PUT/CTL
066D 301A 00755 JR NC,@CHNIO ;Branch if special
066F DD6E01 00756 LD L,(IX+1) ; else p/u the vector
0672 DD6602 00757 LD H,(IX+2)
0675 78 00758 $D1 LD A,B ;Xfer I/O code
0676 FE02 00759 CP 2 ;Set flags state
0678 E9 00760 JP (HL)
0679 C1 00761 RSTBNK POP BC ;Get old bank data
067A F5 00762 PUSH AF ;Can't affect AF
067B 79 00763 LD A,C ;Request to A
067C CD7708 00764 CALL @BANK ;Bring back original bank
067F F1 00765 POP AF
0680 D1 00766 @RSTREG POP DE ;Restore regs
0681 E1 00767 POP HL
0682 DDE1 00768 POP IX
0684 C1 00769 POP BC
0685 C9 00770 RET
00771 ;
0686 E5 00772 $D2 PUSH HL
0687 DDE1 00773 POP IX
0689 DD6E01 00774 @CHNIO LD L,(IX+1) ;P/u vector address
068C DD6602 00775 LD H,(IX+2)
068F DD7E00 00776 $D3 LD A,(IX+0) ;P/u the DCB type
0692 B7 00777 OR A ;File Control Block?
0693 FA0013 00778 JP M,@BYTEIO
0696 CB5F 00779 BIT 3,A ;Test NIL bit 2nd
0698 2024 00780 JR NZ,$D5
069A CB67 00781 BIT 4,A ;Routed?
069C 20E8 00782 JR NZ,$D2 ;Go get routed DCB
069E CB6F 00783 BIT 5,A ;If not linked, then
06A0 28D3 00784 JR Z,$D1 ; must be filtered
06A2 E5 00785 PUSH HL ;Point to the link DCB
06A3 DDE1 00786 POP IX
06A5 DD7003 00787 LD (IX+3),B ;Save the direction
06A8 DDE5 00788 PUSH IX
06AA CD8906 00789 CALL @CHNIO ;I/O to 1st device
06AD DDE1 00790 POP IX
06AF DD4603 00791 LD B,(IX+3) ;P/u the direction
06B2 200C 00792 JR NZ,$D6 ;Go on NZ flag
00793 ;
00794 ; Z-flag on return - check input/output
00795 ;
06B4 CB40 00796 BIT 0,B ;If input & got char,
06B6 DD6E04 00797 $D4 LD L,(IX+4) ; p/u the linked DCB
06B9 DD6605 00798 LD H,(IX+5)
06BC 28C8 00799 JR Z,$D2
06BE BF 00800 $D5 CP A
06BF C9 00801 RET
00802 ;
00803 ; 1st link got NZ condition - if input, get link
00804 ;
06C0 CB40 00805 $D6 BIT 0,B ;Was it input/output?
06C2 2803 00806 JR Z,$D7 ;Output is error
06C4 B7 00807 OR A ;If A=0, then no input
06C5 28EF 00808 JR Z,$D4
06C7 B7 00809 $D7 OR A
06C8 C9 00810 RET
06C9 00811 *GET MULDIV:3 ;16-bit MULT & DIV
00812 ;MULDIV/ASM - 16 x 8 multiplication & division
00815 *MOD
00816 ;
00817 ; Multiply HL by A - SVC 91
00818 ; HL => multiplicand
00819 ; A => multiplier
00820 ; HLA <= 24-bit result
00821 ; DE destroyed
00822 ;
06C9 C5 00823 @MUL16 PUSH BC ;Save reg BC
06CA EB 00824 EX DE,HL ;Multiplicand to DE
06CB 4F 00825 LD C,A ; & multiplier to C
06CC 210000 00826 LD HL,0 ;Init value to zero
06CF 7D 00827 LD A,L ; in regs HLA
06D0 0608 00828 LD B,8 ;Init for 8-bit mult
06D2 29 00829 $E1 ADD HL,HL ;Shift to next place
06D3 17 00830 RLA ;Use A for bits 16-23
06D4 CB01 00831 RLC C ;Multiply this bit?
06D6 3003 00832 JR NC,$E2 ;Go if not
06D8 19 00833 ADD HL,DE ;Else add multiplicand
06D9 CE00 00834 ADC A,0 ; & any overflow to 16
06DB 10F5 00835 $E2 DJNZ $E1 ;Loop for 8 bits
06DD 4F 00836 LD C,A ;Tempy save
06DE 7D 00837 LD A,L ;Xfer low-order to A
06DF 6C 00838 LD L,H ;Xfer mid-order to L
06E0 61 00839 LD H,C ;Xfer hi-order to H
06E1 C1 00840 POP BC
06E2 C9 00841 RET
00842 ;
00843 ; Divide HL by A - SVC 94
00844 ; HL => dividend
00845 ; A => divisor
00846 ; HL <= resulting quotient
00847 ; A <= remainder
00848 ;
00849 *MOD
06E3 D5 00850 @DIV16 PUSH DE ;Save this reg pair
06E4 57 00851 LD D,A ;Xfer divisor to D
06E5 1E10 00852 LD E,16 ;Init for 16-bits
06E7 AF 00853 XOR A
06E8 29 00854 $F1 ADD HL,HL ;Rotate dividend
06E9 17 00855 RLA ; & subtract divisor if
06EA 3803 00856 JR C,$F2 ; carry into bit-16
06EC BA 00857 CP D ;Compare divisor
06ED 3802 00858 JR C,$F3 ;Go if no subtract
06EF 92 00859 $F2 SUB D ; else subtract divisor
06F0 2C 00860 INC L ;Set lo-order
06F1 1D 00861 $F3 DEC E ;Count down one bit
06F2 20F4 00862 JR NZ,$F1 ;Loop for 16-bits
06F4 D1 00863 POP DE
06F5 C9 00864 RET
00865 ;
00866 ; @HEXDEC - SVC 97
00867 ; Routine to convert 16-bit hexadecimal to decimal
00868 ; HL => value
00869 ; DE => buffer pointer of 5-character buffer
00870 ; HL <= destroyed (always set to zero)
00871 ; DE <= Buffer+5
00872 ; BC <= destroyed
00873 ; Z <= set
00874 ;
00875 *MOD
06F6 0605 00876 @HEXDEC LD B,5 ;Length max
06F8 3E20 00877 @HEXD LD A,' ' ;Load blank
06FA 12 00878 HEXDEC1 LD (DE),A ;To string
06FB 13 00879 INC DE ;Bump pointer
06FC 10FC 00880 DJNZ HEXDEC1 ;Go for length
06FE D5 00881 PUSH DE ;Save end +1
06FF 1B 00882 DEC DE ;Adjust back
0700 3E0A 00883 HEXDEC2 LD A,10 ;Base to convert to
0702 CDE306 00884 CALL @DIV16 ;HL+A = HL/A
0705 C630 00885 ADD A,'0' ;Add ASCII to result
0707 12 00886 LD (DE),A ; to user string
0708 1B 00887 DEC DE ;Move back
00888 ;
00889 ; Check if done
00890 ;
0709 7C 00891 LD A,H ;Get subtotal remainder
070A B5 00892 OR L ;Done?
070B 20F3 00893 JR NZ,HEXDEC2 ;Go till completed
070D D1 00894 POP DE ;Restore end+1
070E C9 00895 RET ;Return Z
00896 ;
070F 00897 *GET CLOCKS:3 ;Hardware task stuff
00898 ;CLOCKS/ASM - LS-DOS 6.2
00901 *MOD
00902 ;
00903 ; Model IV time clock & blinking cursor
00904 ;
070F 3C 00905 TIMETBL DB 60,60,24,30 ;Sec/min, min/hr, hr/day
3C 18 1E
00906 TIMTSK$
0713 3A970B 00907 LD A,(CRSAVE) ;If cursor not on,
0716 B7 00908 OR A ; then don't blink
0717 217F00 00909 LD HL,VFLAG$ ;Point to video flag
071A 2829 00910 JR Z,$H2
00911 ;Check if blinking
071C CB7E 00912 BIT 7,(HL) ;Check system INHIBIT
071E CBBE 00913 RES 7,(HL) ;Allow blink next time
0720 2023 00914 JR NZ,$H2
0722 34 00915 INC (HL) ;Increment the counter
0723 CB5E 00916 BIT 3,(HL) ; & see if to 8
0725 281E 00917 JR Z,$H2 ;Not this time
0727 CB9E 00918 RES 3,(HL) ;Reset counter
0729 CB76 00919 BIT 6,(HL) ;Check if SOLID cursor
072B 2802 00920 JR Z,NOSOLID ;If not, then blink
072D CBEE 00921 SET 5,(HL) ;Force SOLID mode
072F CD1708 00922 NOSOLID CALL ENADIS_DO_RAM ;Bring up the video RAM
0732 7E 00923 LD A,(HL) ;Grab the toggle bit
0733 EE20 00924 XOR 20H ; and flip it
0735 77 00925 LD (HL),A
0736 E620 00926 AND 20H ;Was it on?
0738 ED5B950B 00927 LD DE,(CURSOR) ;Get the cursor pos
073C 3A970B 00928 LD A,(CRSAVE) ; and char under cursor
073F 2003 00929 JR NZ,$H1 ;Put character if flip on
0741 3A980B 00930 LD A,(CRSCHAR) ; else put the cursor
0744 12 00931 $H1 LD (DE),A ;Put the char
0745 DD210F07 00932 $H2 LD IX,TIMETBL ;Point to data area
0749 DD3503 00933 DEC (IX+3) ;Count down by 30
074C C0 00934 RET NZ ;Back if not one second
00935 IF @HZ50
00936 LD (IX+3),25 ;Set for 50 hertz
00937 HERTZ$ EQU $-1
00938 ELSE ; else use 60 hertz
074D DD36031E 00939 LD (IX+3),30 ;Reset for one second
0750 00940 HERTZ$ EQU $-1
00941 ENDIF
0751 CB66 00942 BIT 4,(HL) ;Is clock on? (VFLAG$)
0753 2804 00943 JR Z,$H3 ;Go if off
0755 118707 00944 LD DE,CLOCK ;Set to display clock
0758 D5 00945 PUSH DE
0759 0603 00946 $H3 LD B,3
075B 212D00 00947 LD HL,TIME$
075E 110F07 00948 LD DE,TIMETBL ;Pt to max sec, min, hr
0761 34 00949 TIMER1 INC (HL) ;Bump time parm
0762 1A 00950 LD A,(DE)
0763 96 00951 SUB (HL)
0764 C0 00952 RET NZ ;Ret if not max
0765 77 00953 LD (HL),A ; else set to 0
0766 2C 00954 INC L ;Pt to next parm
0767 1C 00955 INC E
0768 10F7 00956 DJNZ TIMER1 ;Loop thru 3 parms
00957 ;
00958 ; Update date at midnight
00959 ;
076A 2E35 00960 LD L,DATE$+2&0FFH ;Point to day of month
076C 7E 00961 LD A,(HL) ;Get the month
076D B7 00962 OR A ;See if date used
076E C8 00963 RET Z ;Back if not
076F 2D 00964 DEC L
0770 110104 00965 LD DE,MAXDAY$ ;Point to test table
0773 34 00966 INC (HL) ;Bump the day
0774 83 00967 ADD A,E
0775 5F 00968 LD E,A
0776 1A 00969 LD A,(DE) ;P/u max days
0777 BE 00970 CP (HL) ;Is day in range?
0778 D0 00971 RET NC ;Return if it is
0779 3601 00972 LD (HL),1 ; else reset day to 1
077B 2C 00973 INC L ; & bump the month
077C 34 00974 INC (HL)
077D 7E 00975 LD A,(HL) ;If went past Dec,
077E D60D 00976 SUB 12+1 ; then need to fix
0780 D8 00977 RET C
0781 3601 00978 LD (HL),1 ;Correct to Jan
0783 2D 00979 DEC L ;Backup to year
0784 2D 00980 DEC L
0785 34 00981 INC (HL)
0786 C9 00982 RET
00983 ;
00984 ; Clock display processor
00985 ;
00986 CLOCK
0787 CD1708 00987 CALL ENADIS_DO_RAM ;Bring up the video
078A 2145F8 00988 LD HL,CRTBGN$+69 ;Point to display CRT
078D 112F00 00989 @TIME LD DE,TIME$+2 ;Point to time$
0790 0E3A 00990 LD C,':' ;Set the separator
0792 0603 00991 TIME1 LD B,3 ;Init for three fields
0794 1A 00992 TIME2 LD A,(DE) ;Get a field item
0795 362F 00993 LD (HL),2FH ;Init display
0797 34 00994 TIME3 INC (HL) ;Bump until proper digit
0798 D60A 00995 SUB 10
079A 30FB 00996 JR NC,TIME3
079C C63A 00997 ADD A,3AH ;Correct the remainder
079E 23 00998 INC HL ;Bump to next display
079F 77 00999 LD (HL),A ; & stuff the digit
07A0 23 01000 INC HL
07A1 05 01001 DEC B
07A2 C8 01002 RET Z ;Back when done
07A3 71 01003 LD (HL),C ; else stuff separator
07A4 23 01004 INC HL
07A5 1B 01005 DEC DE ;Point to next field
07A6 18EC 01006 JR TIME2 ; & loop
01007 ;
01008 ; Return formatted date, HL => user buffer
01009 ;
01010 IF @BLD631
01011 DATELO$ ;<631>
01012 ELSE
01013 @DATE
01014 ENDIF
07A8 113500 01015 LD DE,DATE$+2
07AB 0E2F 01016 LD C,'/'
07AD 18E3 01017 JR TIME1
01018 ;
07AF 0000 01019 PCSAVE$ DW 00 ;PC at entry to RST 38
01020 ;
01021 ; Dynamic Trace routine
01022 ;
01023 TRACE_INT
07B1 B307 01024 DW $+2
07B3 2AAF07 01025 LD HL,(PCSAVE$)
07B6 EB 01026 EX DE,HL ;Program counter to DE
07B7 CD1708 01027 CALL ENADIS_DO_RAM ;Bring up the video
07BA 213EF8 01028 LD HL,CRTBGN$+62 ;Crt trace adr
01029 ;
01030 ; Hexadecimal display routine
01031 ;
07BD 7A 01032 @HEX16 LD A,D ;Convert reg D to
07BE CDC207 01033 CALL @HEX8 ; two hex digits
07C1 7B 01034 LD A,E ;Convert reg E to
07C2 F5 01035 @HEX8 PUSH AF ; two hex digits
07C3 1F 01036 RRA ;Do left nybble first
07C4 1F 01037 RRA
07C5 1F 01038 RRA
07C6 1F 01039 RRA
07C7 CDCB07 01040 CALL HXD1 ;Bits 0-3 stuffed in hex
07CA F1 01041 POP AF ;Reget the byte
07CB E60F 01042 HXD1 AND 0FH ; & use right nybble
07CD C690 01043 ADD A,90H ;Convert nybble to hex
07CF 27 01044 DAA
07D0 CE40 01045 ADC A,40H
07D2 27 01046 DAA
07D3 77 01047 LD (HL),A ;Stuff in (HL)
07D4 23 01048 INC HL
07D5 C9 01049 RET
01050 ;
01051 ; Scan for PAUSE or BREAK & set KFLAG$
01052 ;
F480 01053 SHIFT EQU 0F480H
01054 IF @USA
F401 01055 KB1 EQU 0F401H
01056 ENDIF
01057 IF @GERMAN
01058 KB1 EQU 0F420H
01059 ENDIF
01060 IF @FRENCH
01061 KB1 EQU 0F408H
01062 ENDIF
F440 01063 KB7 EQU 0F440H
07D6 CD1708 01064 KCK@ CALL ENADIS_DO_RAM ;Bring up the keyboard
07D9 217400 01065 LD HL,KFLAG$ ;Hang onto flag
07DC 3A80F4 01066 LD A,(SHIFT) ;P/u SHIFT row & ignore
07DF E607 01067 AND 7 ; CTRL key pressed
07E1 2F 01068 CPL
07E2 CB57 01069 BIT 2,A
07E4 C8 01070 RET Z ;Back if CTRL
01071 ;
01072 ; Set carry flag if a SHIFT key is down
01073 ;
07E5 C601 01074 ADD A,1 ;Set CF if no SHIFT
07E7 3F 01075 CCF ;Set CF if SHIFT
07E8 300B 01076 JR NC,KCK1 ;No pause if no SHIFT
07EA 3A01F4 01077 LD A,(KB1) ;Test for "@"
01078 IF @USA
07ED CB47 01079 BIT 0,A
01080 ENDIF
01081 IF @INTL
01082 BIT 4,A ;Foriegn keyboard
01083 ENDIF
07EF 280B 01084 JR Z,KCK1A ;Bypass if no "@"
07F1 CBCE 01085 SET 1,(HL) ;Turn on pause bit
07F3 1807 01086 JR KCK1A
01087 ;
01088 ; Inhibit test of unshifted BREAK if nested ENA_DO
01089 ;
07F5 3A3508 01090 KCK1 LD A,(OPREG_SV_PTR) ;If not at highest level
07F8 D66F 01091 SUB OPREG_SV_AREA+1&0FFH ; then don't allow
07FA 2009 01092 JR NZ,KCK1B ; tasker BREAK handler
07FC 3A40F4 01093 KCK1A LD A,(KB7) ;Check on BREAK & ENTER
07FF CB47 01094 BIT 0,A ;Check on ENTER
0801 2802 01095 JR Z,KCK1B ;Go if not
0803 CBD6 01096 SET 2,(HL) ; else note set
0805 CB57 01097 KCK1B BIT 2,A ;Is depressed?
0807 F5 01098 PUSH AF
0808 280B 01099 JR Z,KCK2 ;Go if not
080A 3809 01100 JR C,KCK2 ;Ignore if shifted
080C 3A7C00 01101 LD A,(SFLAG$) ;Permit break bit only
080F CB67 01102 BIT 4,A ; if BREAK enabled?
0811 2002 01103 JR NZ,KCK2
0813 CBC6 01104 SET 0,(HL) ;Turn on BREAK bit
0815 F1 01105 KCK2 POP AF ;C=shift, NZ=break
0816 C9 01106 RET
01107 ;
01108 ; Routine to enable video RAM & change stack if necessary
01109 ;
01110 *MOD
01111 ENADIS_DO_RAM
0817 F3 01112 DI ;Can't while we test stack
0818 226B08 01113 LD (HLSAV),HL ;Save HL but not on stack
081B F5 01114 PUSH AF ;Save AF
081C E1 01115 POP HL
081D 226608 01116 LD (AFSAV),HL
0820 21030C 01117 LD HL,0C03H ;Can't exceed X'F3FC'
0823 39 01118 ADD HL,SP
0824 3009 01119 JR NC,$I1
01120 ;
01121 ; Switch to the system stack
01122 ;
0826 E1 01123 POP HL ;Transfer RET address
0827 ED736308 01124 LD (SPSAV),SP ;Save stack pointer
082B 314003 01125 LD SP,STACK$-40H ;Keep room at top
082E E5 01126 PUSH HL ;Put RET back
082F 214608 01127 $I1 LD HL,DIS_DO_RAM ;Stack return to disable
0832 E3 01128 EX (SP),HL ; video RAM below RET
0833 E5 01129 PUSH HL
0834 216E08 01130 LD HL,OPREG_SV_AREA
0835 01131 OPREG_SV_PTR EQU $-2
0837 23 01132 INC HL ;Get next save location
0838 3A7800 01133 LD A,(OPREG$) ;P/u port mask
083B 3002 01134 JR NC,$I2 ;Bypass if NC (no stack switch)
083D E67F 01135 AND 7FH ;Strip bit 7 to use as flag
083F 77 01136 $I2 LD (HL),A ;Save current state
0840 E6FC 01137 AND 0FCH ;Strip SEL1 & SEL0
0842 F682 01138 OR 82H ;Set SEL1,0 = (1,0) & NZ condx
0844 1812 01139 JR DOOPREG ;Set new assignment
01140 ;
01141 ; Routine to disable video RAM
01142 ;
01143 DIS_DO_RAM
0846 F3 01144 DI ;Interrupts off
0847 226B08 01145 LD (HLSAV),HL ;Save off of stack
084A F5 01146 PUSH AF
084B E1 01147 POP HL ;Save AF
084C 226608 01148 LD (AFSAV),HL
084F 2A3508 01149 LD HL,(OPREG_SV_PTR)
0852 7E 01150 LD A,(HL) ;P/u previous state
0853 CB7F 01151 BIT 7,A ;Test if we switch stack
0855 CBFF 01152 SET 7,A ;Make sure PAGE is set
0857 2B 01153 DEC HL
01154 ;
0858 223508 01155 DOOPREG LD (OPREG_SV_PTR),HL
085B 327800 01156 LD (OPREG$),A ;Restore port image
085E D384 01157 OUT (@OPREG),A ; and the port
0860 2003 01158 JR NZ,$I3
01159 ;
01160 ; Switch back to the old stack
01161 ;
0862 310000 01162 LD SP,$-$ ;Get the old stack
0863 01163 SPSAV EQU $-2
0865 210000 01164 $I3 LD HL,$-$
0866 01165 AFSAV EQU $-2
0868 E5 01166 PUSH HL ;Restore AF
0869 F1 01167 POP AF
086A 210000 01168 LD HL,$-$ ;Restore HL
086B 01169 HLSAV EQU $-2
086D FB 01170 EI ;Interrupts back on
086E C9 01171 RET
086E 01172 OPREG_SV_AREA EQU $-1
086F 00 01173 DB 0,0,0,0,0,0,0,0
00 00 00 00 00 00 00
01174 ;
01175 ; Bank selection SVC handler
01176 ; HL=> transfer address for function B=0
01177 ; C => Bank request <0-2>; Set bit 7 to transfer
01178 ; B => Request function
01179 ; 0 => Select bank C
01180 ; 1 => Reset in-use bit of bank C
01181 ; 2 => Test in-use bit of bank C
01182 ; 3 => Set in-use bit of bank C
01183 ;
01184 *MOD
01185 @BANK
0877 E67F 01186 AND 7FH ;Strip possible bit 7
0879 FE03 01187 CP 2+1 ;Bank out of range?
087B D2ED0D 01188 JP NC,PERR
087E 05 01189 DEC B ;Check option
087F FAB308 01190 JP M,$J3 ;Go if bank select
0882 0E86 01191 LD C,86H ;Set for reset BUR$
0884 2819 01192 JR Z,$J1 ;Go if function 1
0886 0E46 01193 LD C,46H ;Set for test BUR$
0888 05 01194 DEC B
0889 2814 01195 JR Z,$J1 ;Go if function 2
088B 05 01196 DEC B
088C 2809 01197 JR Z,$J0 ;Go on set BUR$
088E 05 01198 DEC B
088F C2ED0D 01199 PERRX JP NZ,PERR ;SVC parameter error
0892 3A0202 01200 LD A,(LBANK$) ;P/u current bank
0895 BF 01201 CP A
0896 C9 01202 RET
0897 47 01203 $J0 LD B,A ;Save the bank requested
0898 CD9F08 01204 CALL $J1 ;Test if in use already
089B C0 01205 RET NZ ;Back if error
089C 78 01206 LD A,B ;Reget the request #
089D 0EC6 01207 LD C,0C6H ;Set for set BUR$
089F E607 01208 $J1 AND 7 ;Strip to bank 0-7
08A1 07 01209 RLCA ;Shift <0-2> to <3-5>
08A2 07 01210 RLCA
08A3 07 01211 RLCA
08A4 B1 01212 OR C ;Merge the code type
08A5 32B008 01213 LD ($J2+1),A ;Change the OP code
08A8 AF 01214 XOR A ;Init Z-flag
08A9 3E08 01215 LD A,8 ;Init "Device not avail
08AB E5 01216 PUSH HL ;Don't alter HL
08AC 210002 01217 LD HL,BUR$ ;Point to bank-used-RAM
08AF CB46 01218 $J2 BIT 0,(HL) ;*** Modified instruction
08B1 E1 01219 POP HL
08B2 C9 01220 RET
08B3 E5 01221 $J3 PUSH HL ;Ck if stack is in upper
08B4 210580 01222 LD HL,8005H ; bank area
08B7 39 01223 ADD HL,SP
08B8 E1 01224 POP HL
08B9 DAED0D 01225 JP C,PERR ;Error if > X'7FFE'
08BC FE01 01226 CP 1 ;Change <0, 1, 2, 3>
08BE 17 01227 RLA ; to <1, 2, 4, 6>
08BF 47 01228 LD B,A ; & save for later
08C0 3A0102 01229 LD A,(BAR$) ;P/u Bank Avail Ram
08C3 A0 01230 AND B ;Is the bank installed?
08C4 20C9 01231 JR NZ,PERRX ;Error if not in machine
08C6 78 01232 LD A,B ;Get the requested bank
08C7 1F 01233 RRA ;Change <1, 2, 4> to
08C8 3F 01234 CCF ; <0, 2, 3> {CF on 0
08C9 CE00 01235 ADC A,0 ; switched to 2 & 4}
08CB 07 01236 RLCA ;Shift bits 0-1
08CC 07 01237 RLCA ; to 4-5 (MBIT0,1)
08CD 07 01238 RLCA
08CE 07 01239 RLCA
08CF 47 01240 LD B,A ;Save bit mask
08D0 3A7800 01241 LD A,(OPREG$) ;P/u current memory
08D3 E68F 01242 AND 08FH ; configuration &
08D5 B0 01243 OR B ; mask off old &
08D6 327800 01244 LD (OPREG$),A ; merge the new
08D9 D384 01245 OUT (@OPREG),A ;Switch the hardware
08DB 3A0202 01246 LD A,(LBANK$) ;Get old bank #
08DE 47 01247 LD B,A ; & save it
08DF 79 01248 LD A,C ;P/u new bank #
08E0 E67F 01249 AND 7FH ;Strip any bit-7
08E2 320202 01250 LD (LBANK$),A ; & save new bank #
08E5 A9 01251 XOR C ;Keep bit-7
08E6 B0 01252 OR B ;Merge in new bank #
08E7 4F 01253 LD C,A ; & replace into C
08E8 CB79 01254 BIT 7,C ;Transfer to new bank?
08EA 0600 01255 LD B,0 ;Init for invoke later
08EC C8 01256 RET Z ;No if bit-7 = 0
08ED E3 01257 EX (SP),HL ;Exchange RET with new
08EE BF 01258 CP A ; transfer & go to it
08EF C9 01259 RET
08F0 01260 @$SYS EQU $ ;Pointer for @GTMOD
01261 IF @USA
08F0 01262 *GET KIDVR:3 ;Keyboard driver
01263 ;KIDVR/ASM - LS-DOS 6.2
01266 *MOD
01267 ;
000A 01268 LF EQU 10
000D 01269 CR EQU 13
F401 01270 KB0 EQU 0F401H ;Row 0 RAM address
F440 01271 KB6 EQU 0F440H ;Row 6 RAM address
F480 01272 SHIFT EQU 0F480H ;Row 7 RAM address
01273 ;
08F0 1831 01274 KIDVR JR KIBGN ;Branch around linkage
08F2 870B 01275 DW KILAST ;Last byte used
08F4 03 01276 DB 3,'$KI'
24 4B 49
08F8 0802 01277 DW KIDCB$ ;Pointer to DCB
08FA 0000 01278 DW 0 ;Spare
08FC 00 01279 KIDATA$ DB 0 ;Last key entered
08FD 00 01280 DB 0 ;Repeat time check
0002 01281 RPTINIT EQU $-KIDATA$
08FE 16 01282 DB 22 ;22 * 33.3ms = .733 sec
0003 01283 RPTRATE EQU $-KIDATA$
08FF 02 01284 DB 2 ;2 x RTC rate
0004 01285 KBROW0 EQU $-KIDATA$
0900 FF 01286 DB -1,-1,-1,-1 ;Image of rows 0-3
FF FF FF
0008 01287 KBROW4 EQU $-KIDATA$
0904 FF 01288 DB -1,-1 ;Image of rows 4-5
FF
000A 01289 KBROW6 EQU $-KIDATA$
0906 FF 01290 DB -1,-1 ;Image of rows 6-7
FF
01291 ;
01292 ; Conversion table for keyboard row 7/8
01293 ;
0908 0D 01294 KBTBL DB CR,1DH,1FH,1FH ;
1D 1F 1F
090C 80 01295 DB 80H,0,0BH,1BH ;
00 0B 1B
0910 0A 01296 DB LF,1AH,8,18H ;
1A 08 18
0914 09 01297 DB 9,19H,20H,20H ;
19 20 20
0918 81 01298 DB 81H,91H,82H,92H ;
91 82 92
091C 83 01299 DB 83H,93H ;
93
01300 ;
01301 ; Table to generate 5B-5F, 7B-7F
01302 ;
091E 2C 01303 SPCLTB DB ',/.;',CR
2F 2E 3B 0D
01304 ;
01305 ; Entry to keyboard driver
01306 ;
0923 79 01307 KIBGN LD A,C ;Get the character
0924 F5 01308 PUSH AF ;Save flags
0925 CD8900 01309 CALL @KITSK ;Hook for KI task
0928 F1 01310 POP AF
01311 ;
01312 ; Screen print (Control-*) processing
01313 ;
0929 CDD50A 01314 CALL TYPAHD ;Chain downstream
092C D0 01315 RET NC ;Ret if not
092D F5 01316 PUSH AF ;Save flag state
092E FE3A 01317 CP ':'
0930 2802 01318 JR Z,$K1 ;Go if screen print
0932 F1 01319 POP AF
0933 C9 01320 RET
01321 ;
01322 ; Perform a screen print
01323 ;
0934 F1 01324 $K1 POP AF ;Clean the stack
0935 3A6D00 01325 @VDPRT LD A,(DFLAG$) ;Check on Graphic bit
0938 07 01326 RLCA
0939 3E3E 01327 LD A,3EH ;Init for LD a,'.'
093B 3002 01328 JR NC,$+4 ;Go if not Graphic
093D 3EFE 01329 LD A,0FEH ;Change to CPR n
093F 325C09 01330 LD ($K4),A ;Stuff cpr or ld
0942 217400 01331 LD HL,KFLAG$ ;Reset the BREAK bit
0945 CB86 01332 RES 0,(HL)
0947 E5 01333 PUSH HL ;Save on stack
0948 210000 01334 LD HL,0 ;Init for row,col
094B 0601 01335 $K2 LD B,1 ;Get a character at the
094D CD990B 01336 CALL @VDCTL ; row-H, col-L
0950 2027 01337 JR NZ,$K6 ;Go on error
0952 FE20 01338 CP 20H
0954 3002 01339 JR NC,$+4 ;Convert control codes
0956 C640 01340 ADD A,40H ; to cap A-Z, +
0958 FE80 01341 CP 80H ;Cvrt anything from X'80'
095A 3802 01342 JR C,$K5 ; thru X'FF' to a '.'
095C 3E2E 01343 $K4 LD A,'.' ; unless graphic bit set
095E CD3D06 01344 $K5 CALL @PRT ;Print the char & loop
0961 2016 01345 JR NZ,$K6
0963 2C 01346 INC L ;Bump column counter
0964 7D 01347 LD A,L ;Check for end-of-line
0965 D650 01348 SUB 80
0967 20E2 01349 JR NZ,$K2 ;Loop if not EOL
0969 6F 01350 LD L,A ;Reset to column 0
096A 2D 01351 DEC L ;Adj for CR force
096B E3 01352 EX (SP),HL ;Get KFLAG$
096C CB46 01353 BIT 0,(HL) ;Exit with A=0 on
096E E3 01354 EX (SP),HL ; entrance of BREAK
096F 2008 01355 JR NZ,$K6
0971 24 01356 INC H ;Bump row counter
0972 7C 01357 LD A,H ;Test for end of screen
0973 FE18 01358 CP 24
0975 3E0D 01359 LD A,CR
0977 20E5 01360 JR NZ,$K5 ;Put the CR & loop
0979 3E0D 01361 $K6 LD A,CR ;Close out with CR if
097B CD3D06 01362 CALL @PRT ; BREAK key detected
097E E1 01363 POP HL ;Pop the KFLAG
097F CB86 01364 RES 0,(HL) ; & reset BREAK bit
0981 1832 01365 JR NOCHAR
01366 ;
01367 ; Driver to scan the keyboard
01368 ;
01369 *MOD
0983 DD21FC08 01370 KISCAN LD IX,KIDATA$ ;Point to data area
0987 210009 01371 LD HL,KIDATA$+KBROW0 ;Load kbd image start
098A 0101F4 01372 LD BC,KB0 ;Load start of keyboard
098D 1600 01373 LD D,0 ;Zero the key counter
098F 0A 01374 $L1 LD A,(BC) ;Load 1st char from kbd
0990 5F 01375 LD E,A
0991 AE 01376 XOR (HL) ;XOR with old value
0992 2026 01377 JR NZ,$L2 ;Go if different
0994 14 01378 INC D ;Bump key counter
0995 23 01379 INC HL ;Bump image pointer
0996 CB01 01380 RLC C ;Go to next row
0998 F28F09 01381 JP P,$L1 ;Loop until end of rows
099B 0A 01382 LD A,(BC) ;Get row 7
099C E678 01383 AND 078H ;Strip SHIFT, CTL
099E 5F 01384 LD E,A
099F AE 01385 XOR (HL)
09A0 2018 01386 JR NZ,$L2
09A2 DD7E00 01387 LD A,(IX+0) ;Key down? It's same as
09A5 B7 01388 OR A ; the last if so
09A6 280D 01389 JR Z,NOCHAR ;Ret if no key
09A8 3A2C00 01390 LD A,(TIMER$) ;Do we repeat the
09AB DD9601 01391 SUB (IX+1) ; same key?
09AE DD9602 01392 SUB (IX+RPTINIT) ;Beyond 0.75 seconds?
09B1 0A 01393 LD A,(BC) ;Get back row 7
09B2 5F 01394 LD E,A
09B3 3869 01395 JR C,$L10 ;Go if yes
09B5 F601 01396 NOCHAR OR 1 ;Else don't repeat
09B7 3E00 01397 LD A,0 ;Show NZ with A=0
09B9 C9 01398 RET
01399 ;
01400 ; Found change in key matrix
01401 ;
09BA 73 01402 $L2 LD (HL),E ;Stuff KB image with new
09BB A3 01403 AND E ; KB row value
09BC CA880A 01404 JP Z,NOKEY ;Go if new is none
01405 ;
01406 ; Convert the depressed key
01407 ;
09BF 5F 01408 LD E,A ;Save the active bit
09C0 7A 01409 LD A,D ;Calculate 8 * row
09C1 07 01410 RLCA
09C2 07 01411 RLCA
09C3 07 01412 RLCA
09C4 57 01413 LD D,A ;Save 8 * row
09C5 0E01 01414 LD C,1 ;Add 8 * row + column
09C7 79 01415 $L3 LD A,C
09C8 A3 01416 AND E ;Check if bits match
09C9 2019 01417 JR NZ,$L6 ;Go if match
09CB 14 01418 INC D ; else bump value
09CC CB01 01419 RLC C ;Shift compare bit
09CE 18F7 01420 JR $L3 ;Loop to test next
01421 ;
01422 ; Key pressed was not an alpha
01423 ;
09D0 D690 01424 $L4 SUB 90H ;Adjust for non-alpha
09D2 3052 01425 JR NC,$L9 ;Go if special key
09D4 C640 01426 ADD A,40H ;Cvrt to numeric/symbol
09D6 FE3C 01427 CP 3CH ;Manipulate to get
09D8 3802 01428 JR C,$L5 ; proper code
09DA EE10 01429 XOR 10H
09DC CB43 01430 $L5 BIT 0,E ;Check SHIFT
09DE 2860 01431 JR Z,$L11 ;Go if unshift
09E0 EE10 01432 XOR 10H ; else adjust for SHIFT
09E2 185C 01433 JR $L11
01434 ;
01435 ; Found a key - Set up the function codes
01436 ;
09E4 3A80F4 01437 $L6 LD A,(SHIFT) ;P/u the SHIFT key
09E7 5F 01438 LD E,A ;Merge RH & LH Shift keys
09E8 E602 01439 AND 2 ;Only merge bit 1
09EA 0F 01440 RRCA ;Bit 1 to bit 0
09EB B3 01441 OR E ;Merge bits 0 & 1
09EC 5F 01442 LD E,A ;Value of (RHorLH) shift
09ED 7A 01443 LD A,D ;Load semi-converted
09EE C660 01444 ADD A,60H ;If alpha, convert to
09F0 FE80 01445 CP 80H ; correct value
09F2 217400 01446 LD HL,KFLAG$
09F5 30D9 01447 JR NC,$L4 ;Go if not alpha
01448 ;
01449 ; Alpha <@-Z> - If caps lock or ,
01450 ; Convert to caps unless CLEAR
01451 ;
09F7 CB53 01452 BIT 2,E ;CTRL key down?
09F9 2018 01453 JR NZ,CTLA2Z ;CTRL sets <00-1A>
09FB FE60 01454 CP 60H ;Invert @ and `
09FD 2004 01455 JR NZ,$L7
09FF EE20 01456 XOR 20H ;Invert & bypass test
0A01 180A 01457 JR $L8 ; for CAPs lock
0A03 DDCB0A4E 01458 $L7 BIT 1,(IX+KBROW6) ;If CLEAR, don't test
0A07 2004 01459 JR NZ,$L8 ; for CAPs lock
0A09 CB6E 01460 BIT 5,(HL) ;Caps lock?
0A0B 2031 01461 JR NZ,TGLCASE
0A0D CB43 01462 $L8 BIT 0,E ;Shift key down?
0A0F 282F 01463 JR Z,$L11 ;Bypass if not shifted
0A11 182B 01464 JR TGLCASE ;Convert to upper case
0A13 D660 01465 CTLA2Z SUB 60H ;Convert CTRL A-Z
0A15 2029 01466 JR NZ,$L11 ;Go on A-Z
0A17 CB43 01467 BIT 0,E ;Shifted?
0A19 37 01468 SCF ;Set C-flag for CTL-@
0A1A C8 01469 RET Z ; & return if unshifted
0A1B 3E1C 01470 LD A,1CH ; else set EOF error
0A1D C9 01471 RET
0A1E 3A2C00 01472 $L10 LD A,(TIMER$) ;Advance time check
0A21 DD8603 01473 ADD A,(IX+RPTRATE) ; by 0.067 seconds
0A24 1872 01474 JR $L12 ;Go output the key
01475 ;
01476 ; Special keys - rows 6 & 7
01477 ;
0A26 FE0B 01478 $L9 CP 11 ;Compress F1-F3 keys
0A28 284F 01479 JR Z,CAPSKEY ; while checking for CAP
0A2A 3802 01480 JR C,$+4 ; F1-F3 to 8-10
0A2C D604 01481 SUB 4
0A2E 210809 01482 LD HL,KBTBL ;Pt to special char table
0A31 07 01483 RLCA ;Index into table,
0A32 CB43 01484 BIT 0,E ; shifted code is +1
0A34 2801 01485 JR Z,$+3
0A36 3C 01486 INC A
0A37 4F 01487 LD C,A ;Index the table
0A38 0600 01488 LD B,0
0A3A 09 01489 ADD HL,BC
0A3B 7E 01490 LD A,(HL) ;Load char from table
0A3C 1802 01491 JR $L11 ;Bypass restore of char
0A3E EE20 01492 TGLCASE XOR 20H ;Toggle the case
0A40 FE80 01493 $L11 CP 80H ;BREAK key?
0A42 200F 01494 JR NZ,$L11A ;Ck on disable
0A44 217C00 01495 LD HL,SFLAG$ ;Break disabled?
0A47 CB66 01496 BIT 4,(HL)
0A49 2007 01497 JR NZ,$L11B ;Don't set bit if disabl
0A4B 217400 01498 LD HL,KFLAG$
0A4E CBC6 01499 SET 0,(HL) ; otherwise set it
0A50 1801 01500 JR $L11A
0A52 17 01501 $L11B RLA ;Rotate bit-7 out
0A53 DDCB0A4E 01502 $L11A BIT 1,(IX+KBROW6) ;CLEAR key pressed?
0A57 280E 01503 JR Z,NOTALPH ;Go if not down
0A59 57 01504 LD D,A ;Save code
0A5A CBAF 01505 RES 5,A ;Set to upper-case for
0A5C D641 01506 SUB 'A' ; test A-Z
0A5E FE1A 01507 CP 'Z'-'A'+1
0A60 7A 01508 LD A,D ;Get back actual char
0A61 3002 01509 JR NC,$+4 ;Go if not A-Z
0A63 EE20 01510 XOR 20H ;Shift keyboard case
0A65 F680 01511 OR 80H ;Set bit 7 for CLEAR key
0A67 CB43 01512 NOTALPH BIT 0,E ;SHIFT key down?
0A69 2819 01513 JR Z,FIXCLR ;Go if not
0A6B FE9F 01514 GOTSHFT CP 9FH ;Shift-clear?
0A6D 2813 01515 JR Z,FIXSCL ;Go if so
0A6F FE20 01516 TSTSPA CP 20H ;Shift 0 or shift sp?
0A71 2016 01517 JR NZ,KEYOK ;Go if not
0A73 DDCB0846 01518 BIT 0,(IX+KBROW4) ;Ck zero key
0A77 2810 01519 JR Z,KEYOK ;Go if not down
01520 ;
01521 ; Toggle the caps lock bit in the KFLAG$
01522 ;
0A79 3E20 01523 CAPSKEY LD A,20H ;CAPs wasn't 20H
0A7B 217400 01524 CASHK$ LD HL,KFLAG$ ;Reverse case by
0A7E AE 01525 XOR (HL) ; flipping bit 5
0A7F 77 01526 LD (HL),A
0A80 1806 01527 JR NOKEY
0A82 EE80 01528 FIXSCL XOR 80H ;Reset bit 7
0A84 FE9F 01529 FIXCLR CP 9FH ;Clear key?
0A86 2001 01530 JR NZ,KEYOK ;Go if not
0A88 AF 01531 NOKEY XOR A
0A89 DD7700 01532 KEYOK LD (IX+0),A
0A8C 018401 01533 LD BC,0184H ;Delay
0A8F CD8203 01534 TYPHK$ CALL PAUSE@
0A92 3A2C00 01535 LD A,(TIMER$) ;Set initialization
0A95 DD8602 01536 DELAY2 ADD A,(IX+RPTINIT) ; repeat key delay
0A98 DD7701 01537 $L12 LD (IX+1),A ;Save new repeat time
0A9B DD7E00 01538 LD A,(IX+0) ;Check if any key
0A9E B7 01539 OR A ; code was saved
0A9F CAB509 01540 JP Z,NOCHAR ;Ret if none
0AA2 CB53 01541 BIT 2,E ;Shift key down?
0AA4 37 01542 SCF ;Init carry
0AA5 2004 01543 JR NZ,SPECL ;Ret if CTRL
0AA7 3F 01544 CCF
0AA8 CB7F 01545 DVREXIT BIT 7,A ;Z-flag set on non-CLEAR
0AAA C8 01546 RET Z ;Go if not CLEAR+key
0AAB F5 01547 SPECL PUSH AF ;Save code
0AAC 211E09 01548 $L13 LD HL,SPCLTB ;Special char table
0AAF CBBF 01549 RES 7,A ;Turn off "CLEAR"
0AB1 015B05 01550 LD BC,5<8!5BH ;5 chars, starting char
0AB4 3001 01551 JR NC,$+3 ; if not CTRL
0AB6 05 01552 DEC B ; else only 4
0AB7 BE 01553 SPCLLP CP (HL) ;Is this it?
0AB8 2812 01554 JR Z,HIT ;Go if so
0ABA EE10 01555 XOR 10H ;Flip shift state
0ABC BE 01556 CP (HL) ;Is that it?
0ABD 280B 01557 JR Z,HITWS ;Go if so
0ABF EE10 01558 XOR 10H ;Flip back
0AC1 23 01559 INC HL ;Bump specl table ptr
0AC2 0C 01560 INC C ;Bump "convert to" char
0AC3 10F2 01561 DJNZ SPCLLP ;Loop through table
0AC5 F1 01562 POP AF ;Not found in table
0AC6 380A 01563 JR C,CKCTL2 ;Ck CTL for C-flag
0AC8 BF 01564 CKCTL1 CP A ;Set Z-flag
0AC9 C9 01565 RET
0ACA CBE9 01566 HITWS SET 5,C ;Move to LC set
0ACC F1 01567 HIT POP AF ;Restore orig char
0ACD 79 01568 LD A,C ;Load converted one
0ACE 30F8 01569 CKCTL JR NC,CKCTL1 ;Go if ctl key not down
0AD0 E61F 01570 AND 1FH ;Force ctl code
0AD2 BF 01571 CKCTL2 CP A ;Set Z-flag
0AD3 37 01572 SCF ;Set C-flag for CTRL
0AD4 C9 01573 RET
01574 ;
01575 ; Check the type ahead buffer for any character
01576 ;
01577 *MOD
01578 TYPAHD
0AD5 CD1708 01579 CALL ENADIS_DO_RAM ;Bring up Keyboard ram
0AD8 2180FF 01580 LD HL,TYPBUF ;P/u start of type buffer
0ADB 36FF 01581 LD (HL),0FFH ;Turn off type ahead
0ADD 381D 01582 JR C,$M1 ;Go on @GET
0ADF 2842 01583 JR Z,TYPON ;No PUT to *KI
0AE1 FE03 01584 CP 3 ;CTL 3 function?
0AE3 CA650B 01585 JP Z,CLRTYP ;Clear buffer if so
0AE6 3C 01586 INC A
0AE7 2803 01587 JR Z,CTLFF ;Go if CTL 255 function
0AE9 AF 01588 XOR A ;Nothing done, No error
0AEA 1837 01589 JR TYPON
01590 ;
01591 ; Handle CTL-255 - scan keyboard into user rowbuf
01592 ;
01593 CTLFF
0AEC 2101F4 01594 LD HL,KB0 ;Start of keyboard image
0AEF 0608 01595 LD B,8 ;Do 8 rows
0AF1 7E 01596 $M0 LD A,(HL) ;P/u the image
0AF2 FD7700 01597 LD (IY),A ; and xfer to user buffer
0AF5 FD23 01598 INC IY
0AF7 CB15 01599 RL L
0AF9 10F6 01600 DJNZ $M0
0AFB C9 01601 RET
01602 ;
0AFC E5 01603 $M1 PUSH HL
0AFD 23 01604 INC HL ;Bump to PUT pointer
0AFE 7E 01605 LD A,(HL) ; & pick it up
0AFF 23 01606 INC HL ;Bump to GET pointer
0B00 BE 01607 CP (HL) ;The same?
0B01 281C 01608 JR Z,$M4 ;Go if so
0B03 E5 01609 PUSH HL ;Save pointer to GETPTR
0B04 5E 01610 LD E,(HL) ;P/u offset to buffer
0B05 23 01611 INC HL ;Pt to buffer start
0B06 1600 01612 LD D,0 ;Add offset to start
0B08 19 01613 ADD HL,DE ; to point to char posn
0B09 46 01614 LD B,(HL) ;GET the stored char
0B0A E1 01615 POP HL ;Rcvr GETPTR
0B0B 34 01616 INC (HL) ;Bump by 1 for char
0B0C 3E50 01617 LD A,80 ;Check for >80
0B0E BE 01618 CP (HL) ; after INC
0B0F 3002 01619 JR NC,$M2 ;Go if not at end
0B11 3600 01620 LD (HL),0 ;Reset to start of buf
0B13 7E 01621 $M2 LD A,(HL) ;If we emptied the
0B14 2B 01622 DEC HL ; type-ahead buffer,
0B15 BE 01623 CP (HL) ; update KFLAG$
0B16 CC6A0B 01624 CALL Z,R7KFLG ;Reset bit-7 if empty
0B19 E1 01625 POP HL ;Pointed to & get switch
0B1A 3600 01626 LD (HL),0 ;Turn type back on
0B1C 78 01627 LD A,B ;Transfer char/flag
0B1D BF 01628 CP A ;Set flag "Z"
0B1E C9 01629 RET
01630 ;
01631 ; No character in type ahead buffer - get from kbd
01632 ;
0B1F CD8309 01633 $M4 CALL KISCAN ;Call keyboard driver
0B22 E1 01634 POP HL ;Rcvr switch
0B23 3600 01635 TYPON LD (HL),0 ;Type ahead back on
0B25 C9 01636 RET
01637 ;
01638 ; Type ahead task 10 - scans keyboard & saves key
01639 ;
0B26 280B 01640 TYPTSK$ DW $M5 ;Task entry for processor
0B28 3A6D00 01641 $M5 LD A,(DFLAG$) ;If type-ahead suppressed
0B2B E602 01642 AND 2H ; then return
0B2D C8 01643 RET Z
0B2E CD1708 01644 CALL ENADIS_DO_RAM ;Bring up the keyboard
0B31 2180FF 01645 LD HL,TYPBUF ;P/u type switch
0B34 7E 01646 LD A,(HL) ;If previous driver is
0B35 B7 01647 OR A ; currently executing,
0B36 C0 01648 RET NZ ; do not stack more keys
0B37 23 01649 INC HL ;Bump to PUTPTR
0B38 E5 01650 PUSH HL ; & save it
0B39 CD8309 01651 KIHOOK CALL KISCAN ; and scan for a character
0B3C E1 01652 POP HL
0B3D C0 01653 RET NZ ;Ret if no char
0B3E F5 01654 PUSH AF ; else xfer char
0B3F C1 01655 POP BC ; & flag to BC
0B40 FE80 01656 CP 80H ;Check for
0B42 F5 01657 PUSH AF
0B43 E5 01658 PUSH HL
0B44 CC660B 01659 CALL Z,$M6 ;If so clear type buf
0B47 E1 01660 POP HL ;Restore
0B48 F1 01661 POP AF
0B49 FEC0 01662 CP 0C0H ;If CLEAR @, reset keybuf
0B4B 2819 01663 JR Z,$M6
0B4D 5E 01664 LD E,(HL) ;P/u PUTPTR & compare
0B4E 7B 01665 LD A,E ;GETPTR
0B4F 23 01666 INC HL
0B50 BE 01667 CP (HL)
0B51 2821 01668 JR Z,$M8 ;Jump if key buffer empty
0B53 3A2C00 01669 LD A,(TIMER$) ;Check if we expired the
0B56 DD8603 01670 ADD A,(IX+RPTRATE) ; time interval between
0B59 DDBE01 01671 CP (IX+1) ; repeating keys
0B5C 2012 01672 JR NZ,$M7 ;Go if time not up
0B5E DD8603 01673 ADD A,(IX+RPTRATE) ;Re-adjust time check so
0B61 DD7701 01674 LD (IX+1),A ; we don't repeat in
0B64 C9 01675 RET ; type-ahead task
01676 ;
01677 ; CLEAR @ control key entered, clear the buffer
01678 ;
0B65 23 01679 CLRTYP INC HL ;Bump to PUT pointer
0B66 AF 01680 $M6 XOR A
0B67 77 01681 LD (HL),A ;1st PUT is loc'n 0
0B68 23 01682 INC HL ;Pt to GETPTR
0B69 77 01683 LD (HL),A ;1st GET is loc'n 0
0B6A 217400 01684 R7KFLG LD HL,KFLAG$ ;Show buffer empty
0B6D CBBE 01685 RES 7,(HL)
0B6F C9 01686 RET
01687 ;
01688 ; Char to stuff - check if buffer will overflow
01689 ;
0B70 7B 01690 $M7 LD A,E ;P/u current PUT pointer
0B71 3C 01691 INC A ;If the next loc'n wraaps
0B72 BE 01692 CP (HL) ; to the GET loc'n,
0B73 C8 01693 RET Z ; don't permit overrun
0B74 E5 01694 $M8 PUSH HL ;Save ptr to GETPTR
0B75 23 01695 INC HL ;Pt to start of keybuf
0B76 1600 01696 LD D,0 ; & calculate PUT loc'n
0B78 19 01697 ADD HL,DE
0B79 70 01698 LD (HL),B ;Store the char
0B7A 217400 01699 LD HL,KFLAG$ ;Show type buffer
0B7D CBFE 01700 SET 7,(HL) ; is not empty
0B7F E1 01701 POP HL ;Rcvr ptr to GETPTR
0B80 2B 01702 DEC HL ;Backup to PUTPTR
0B81 34 01703 INC (HL) ;Bump past the char
0B82 3E50 01704 LD A,80 ;Check for >80
0B84 BE 01705 CP (HL)
0B85 D0 01706 RET NC ;Back if not over 80
0B86 72 01707 LD (HL),D ; else reset to 1st
0B87 C9 01708 RET ; position in buf (0)
01709 ;
01710 ; Type ahead buffer area
01711 ;
FF80 01712 TYPBUF EQU 0FF80H
01713 ;
01714 ; TYPBUF+0 = On/Off Flag
01715 ; TYPBUF+1 = Storage pointer
01716 ; TYPBUF+2 = Retrieve pointer
01717 ; TYPBUF+3 = Start of actual buffer
01718 ;
0B87 01719 KILAST EQU $-1
01720 ENDIF
01721 IF @GERMAN
01722 FREN EQU 00
01723 GERM EQU -1
01725 ENDIF
01726 IF @FRENCH
01727 FREN EQU -1
01728 GERM EQU 00
01730 ENDIF
0B88 01731 *GET DODVR:3 ;Video driver
01732 ;DODVR/ASM - LS-DOS 6.2
01735 *MOD
0084 01736 @OPREG EQU 84H ;Mem mgt & video control
0088 01737 CRTCADD EQU 88H ;CRTC address port
0089 01738 CRTCDAT EQU 89H ;CRTC data port
0050 01739 LINESIZ EQU 80
0018 01740 NUMROWS EQU 24
FFB0 01741 NEGLINE EQU -LINESIZ
0780 01742 CRTSIZE EQU LINESIZ*NUMROWS
0800 01743 RAMSIZE EQU 2048
F800 01744 CRTBGN$ EQU 0F800H
FF7F 01745 CRTEND EQU CRTBGN$+CRTSIZE-1
01746 ;
01747 ; Driver entry point
01748 ;
0B88 1812 01749 DODVR JR DOBGN ;Branch around linkage
0B8A 000E 01750 DW DOEND ;Last memory location used
0B8C 03 01751 DB 3,'$DO'
24 44 4F
0B90 1002 01752 DW DODCB$ ;DCB used
0B92 0000 01753 DW 0 ;Reserved
0B94 01754 DODATA$ EQU $
0000 01755 DO_MASK EQU $-DODATA$
0007 01756 SCRPROT EQU 7 ;Bits 0-2: scroll protect
0003 01757 TABS EQU 3 ;Bit 3: 0=tabs, 1=chars
0004 01758 CTL EQU 4 ;Bit 4, display controls
01759 IF @USA
0B94 00 01760 DB 0 ;Tab/Spec, Scroll protect
01761 ENDIF
01762 IF @INTL
01763 DB 08 ;Space compression off
01764 ENDIF
0B95 00F8 01765 CURSOR DW CRTBGN$
0B97 20 01766 CRSAVE DB 20H ;Character under cursor
0B98 5F 01767 CRSCHAR DB '_' ;Cursor character
01768 ;
01769 ; Entry from SVC 15, @VDCTL
01770 ;
0B99 C3420D 01771 @VDCTL JP @_VDCTL
01772 ;
01773 ; Continue regular driver functions
01774 ;
0B9C DD21940B 01775 DOBGN LD IX,DODATA$
0BA0 CD1708 01776 CALL ENADIS_DO_RAM ;Bring up the video RAM
0BA3 DAB30D 01777 JP C,$N0 ;Go on 'GET' request
0BA6 CDB30D 01778 CALL $N0 ;Handle cursor
0BA9 C5 01779 PUSH BC ;Need to save C
0BAA 79 01780 LD A,C ;Get char to display
0BAB DDCB0066 01781 BIT CTL,(IX+DO_MASK) ;Display controls set?
0BAF 2009 01782 JR NZ,$N1A ;Go if so
0BB1 B7 01783 OR A ;Char a 0?
0BB2 CA9F0C 01784 JP Z,TGGLCTL ;Switch Bit CTL if so
0BB5 FE20 01785 CP 20H ;Video control char?
0BB7 DA440C 01786 JP C,DO_CONTROL ;Go if so
0BBA FEC0 01787 $N1A CP 0C0H ;Tab or special?
0BBC 3806 01788 JR C,DONORM ;Go on normal characters
01789 ;
01790 ; Character is => 0C0H
01791 ;
0BBE DDCB005E 01792 BIT TABS,(IX+DO_MASK) ;Tabs or spec chars
0BC2 2826 01793 JR Z,DO_TABS ;Go if video tabs
01794 ;
01795 ; Character is not tab expansion - do it
01796 ;
0BC4 CDB80C 01797 DONORM CALL DO_DSPCHAR ;Display the char
0BC7 DDCB00A6 01798 RES CTL,(IX+DO_MASK) ;Turn off CTL bit
0BCB C1 01799 DO_RET POP BC ;Get orig char
0BCC F3 01800 DO_RET1 DI ;Disable intr
0BCD 3A970B 01801 LD A,(CRSAVE) ;If a cursor is on, then
0BD0 B7 01802 OR A ; we need to save the
0BD1 2810 01803 JR Z,$N1 ; current char & display
0BD3 1A 01804 LD A,(DE) ; the cursor character
0BD4 32970B 01805 LD (CRSAVE),A ;Save current char
0BD7 3A7F00 01806 LD A,(VFLAG$) ;Allow tasker to blink
0BDA CBBF 01807 RES 7,A
0BDC 327F00 01808 LD (VFLAG$),A
0BDF 3A980B 01809 LD A,(CRSCHAR) ;P/u cusor character
0BE2 12 01810 LD (DE),A ;Put it on the screen
0BE3 ED53950B 01811 $N1 LD (CURSOR),DE ;Update cursor position
0BE7 BF 01812 CP A ;Clear status
0BE8 79 01813 LD A,C ;Restore the char
0BE9 C9 01814 RET
01815 ;
01816 ; Perform a tab expansion {C0H-FFH}
01817 ;
01818 DO_TABS
0BEA D6C0 01819 SUB 0C0H ;Compute spaces
0BEC 28DD 01820 JR Z,DO_RET ;Forget it if TAB(0)
0BEE 47 01821 LD B,A ;Display requested
0BEF 0E20 01822 $N2 LD C,' ' ; number of spaces
0BF1 CDB80C 01823 CALL DO_DSPCHAR
0BF4 10F9 01824 DJNZ $N2
0BF6 18D3 01825 JR DO_RET
01826 ;
01827 ; Routine to move the cursor to begin of line {29}
01828 ;
01829 CRSBOL
0BF8 EB 01830 EX DE,HL ;Cursor addr to HL
0BF9 CDF40D 01831 CALL ADDR1 ;Find row,col
0BFC 6F 01832 LD L,A ;Set col to start
0BFD C3D00D 01833 JP ROWCOL_2_ADDR ;Calc address of BOL
01834 ;
01835 ; Routines to turn on/off the cursor {14/15}
01836 ;
0C00 1A 01837 CRSON LD A,(DE) ;Get screen character
0C01 32970B 01838 CRSOFF LD (CRSAVE),A ;Save zero or CRT char
0C04 C9 01839 RET
01840 ;
01841 ; Routine moves cursor to start of video page {28}
01842 ; set to 80 column, and turns off inverse video
01843 ;
01844 CRSHOME
0C05 1100F8 01845 LD DE,CRTBGN$ ;Home the cursor
0C08 3A7600 01846 LD A,(MODOUT$) ;P/u the mask &
0C0B E6FB 01847 AND 0FBH ; set to 80 cpl
0C0D CDB20C 01848 CALL SETMOD
0C10 187A 01849 JR DO_INVERT_DIS ;Set to normal video
01850 ;
01851 ; Routine to backspace & erase cursor {08}
01852 ;
01853 BACKSPA
0C12 CD1B0C 01854 CALL CRSBKSP ;Backspace the cursor
0C15 C8 01855 RET Z ;If not at start,
0C16 0E20 01856 LD C,' ' ; put a space at
0C18 C3CA0D 01857 JP PUT_@ ; at the new loc'n
01858 ;
01859 ; Routine to backspace the cursor {24}
01860 ;
01861 CRSBKSP
0C1B 3A7600 01862 LD A,(MODOUT$) ;If double width chars,
0C1E E604 01863 AND 4 ; need to do twice
0C20 C4230C 01864 CALL NZ,$+3
0C23 2100F8 01865 LD HL,CRTBGN$ ;See if at home position
0C26 ED52 01866 SBC HL,DE ; prior to adjusting
0C28 C8 01867 RET Z
0C29 1B 01868 DEC DE ;Decrement the cursor pos
0C2A C9 01869 RET
01870 ;
01871 ; Routine to move the cursor up one line {27}
01872 ;
01873 CRSUP
0C2B 21B0FF 01874 LD HL,NEGLINE ;Move up one line
0C2E 1803 01875 JR MOVCRS
01876 ;
01877 ; Routine to move the cursor down one line {26}
01878 ;
01879 CRSDOWN
0C30 215000 01880 LD HL,LINESIZ ;Add the line length
0C33 19 01881 MOVCRS ADD HL,DE ; to the current pos
0C34 7C 01882 LD A,H ;Make sure we did not
0C35 FEF8 01883 CP CRTBGN$<-8 ; go over the top
0C37 D8 01884 RET C
0C38 EB 01885 EX DE,HL ; & switch back to DE
0C39 1B 01886 DEC DE ;Adjust for fall thru
0C3A C3C30C 01887 JP CRSFRW0
01888 ;
01889 ; Set to 40 cpl mode {23}
01890 ;
0C3D 3A7600 01891 SET40 LD A,(MODOUT$) ;Get image of the port
0C40 F604 01892 OR 04H ;Merge in 40 cpl bit
0C42 186E 01893 JR SETMOD
01894 ;
01895 ; Routines to parse control functions
01896 ;
01897 DO_CONTROL
0C44 21CB0B 01898 LD HL,DO_RET ;Establish RET
0C47 E5 01899 PUSH HL
0C48 FE08 01900 CP 08H ;Backspace?
0C4A 28C6 01901 JR Z,BACKSPA
0C4C FE0A 01902 CP 0AH ;Line feed?
0C4E 2802 01903 JR Z,$+4 ; is same as
0C50 D60D 01904 SUB 0DH ;Carriage return?
0C52 CA020D 01905 JP Z,LINFEED
0C55 3D 01906 DEC A ;Cursor on?
0C56 28A8 01907 JR Z,CRSON
0C58 3D 01908 DEC A ;Cursor off?
0C59 28A6 01909 JR Z,CRSOFF
0C5B 3D 01910 DEC A ;Reverse video?
0C5C 282B 01911 JR Z,DO_INVERT_ENA
0C5E 3D 01912 DEC A
0C5F 283A 01913 JR Z,DO_INVERT_OFF
0C61 D604 01914 SUB 4 ;Swap tab/alternate?
0C63 2841 01915 JR Z,TGGLTAB
0C65 3D 01916 DEC A ;Special/alternate?
0C66 2845 01917 JR Z,TGGLALT
0C68 3D 01918 DEC A ;40 cpl?
0C69 28D2 01919 JR Z,SET40
0C6B 3D 01920 DEC A ;Cursor backspace?
0C6C 28AD 01921 JR Z,CRSBKSP
0C6E 3D 01922 DEC A ;Cursor forward?
0C6F 284A 01923 JR Z,CRSFRWD
0C71 3D 01924 DEC A ;Cursor down?
0C72 28BC 01925 JR Z,CRSDOWN
0C74 3D 01926 DEC A ;Cursor up?
0C75 28B4 01927 JR Z,CRSUP
0C77 3D 01928 DEC A ;Cursor home?
0C78 CA050C 01929 JP Z,CRSHOME
0C7B 3D 01930 DEC A ;Cursor BOL?
0C7C CAF80B 01931 JP Z,CRSBOL
0C7F 3D 01932 DEC A ;Clear to EOL?
0C80 CA120D 01933 JP Z,CLREOL
0C83 3D 01934 DEC A
0C84 CA1E0D 01935 JP Z,CLREOF ;Clear to end-of-frame?
0C87 AF 01936 XOR A ;Clear A reg.
0C88 C9 01937 RET
01938 ;
01939 ; Routine to enable inverse video
01940 ;
01941 DO_INVERT_ENA
0C89 0608 01942 LD B,8 ;Set for enable
0C8B 21 01943 DB 21H ;Ignore next load
01944 DO_INVERT_DIS
0C8C 0600 01945 LD B,0
0C8E 2A3508 01946 LD HL,(OPREG_SV_PTR) ;Real OPREG$
0C91 7E 01947 LD A,(HL) ;P/u OPREG mask
0C92 E6F7 01948 AND 0F7H ;Strip bit 3
0C94 B0 01949 OR B ;Set/reset invideo bit
0C95 77 01950 LD (HL),A ; and restuff
0C96 78 01951 LD A,B ;Get mode mask byte
0C97 07 01952 RLCA ;Rotate left 4 times to
0C98 07 01953 RLCA ; make an 8 into 80H
0C99 07 01954 RLCA ; for inverse on
0C9A 07 01955 RLCA ;Inverse off remains 0
01956 DO_INVERT_OFF
0C9B 32CB0D 01957 LD (INVIDEO),A ;Set the mask byte
0C9E C9 01958 RET
01959 ;
01960 ; Routine to toggle display of controls
01961 ;
0C9F 21CB0B 01962 TGGLCTL LD HL,DO_RET ;Establish ret addr
0CA2 E5 01963 PUSH HL
0CA3 3E10 01964 LD A,10H ;Toggle bit 4
0CA5 21 01965 DB 21H ;Ignore next
01966 ;
01967 ; Toggle tabs & alternate character set
01968 ;
01969 TGGLTAB
0CA6 3E08 01970 LD A,8 ;Toggle bit 3
0CA8 DDAE00 01971 XOR (IX+DO_MASK) ;P/u mask value
0CAB 1850 01972 JR SETMASK
01973 ;
01974 ; Toggle special & alternate character set
01975 ;
01976 TGGLALT
0CAD 3A7600 01977 LD A,(MODOUT$) ;P/u port mask
0CB0 EE08 01978 XOR 8 ;Flip the bit
0CB2 327600 01979 SETMOD LD (MODOUT$),A ;Resave port mask
0CB5 D3EC 01980 OUT (0ECH),A ; and send the byte
0CB7 C9 01981 RET
01982 ;
01983 ; Display character at current cursor position
01984 ;
01985 DO_DSPCHAR
0CB8 CDCA0D 01986 CALL PUT_@ ;Display the char
01987 ;
01988 ; Routine to perform cursor forward {25}
01989 ;
01990 CRSFRWD
0CBB 3A7600 01991 LD A,(MODOUT$) ;If double width chars,
0CBE E604 01992 AND 4 ; need to do twice
0CC0 2801 01993 JR Z,CRSFRW0
0CC2 13 01994 INC DE ;Move cursor forward
0CC3 13 01995 CRSFRW0 INC DE
0CC4 217FFF 01996 LD HL,CRTEND ;Off the screen?
0CC7 ED52 01997 SBC HL,DE
0CC9 D0 01998 RET NC ;Back if not
0CCA CD2B0C 01999 CALL CRSUP ;Put cursor back on
0CCD D5 02000 PUSH DE ;Save cursor position
02001 DO_SCROLL
0CCE DD7E00 02002 LD A,(IX+DO_MASK) ;Get scroll protect
0CD1 E607 02003 AND SCRPROT
0CD3 2100F8 02004 LD HL,CRTBGN$ ;Point to CRT start
0CD6 118007 02005 LD DE,CRTSIZE ;P/u CRT size
0CD9 C5 02006 PUSH BC
0CDA 015000 02007 LD BC,LINESIZ ;Set line size
0CDD 3C 02008 INC A ;Adjust scroll protect
0CDE 09 02009 $N4 ADD HL,BC ;Move logical start
0CDF EB 02010 EX DE,HL ; down one line
0CE0 B7 02011 OR A ; and subtract one line
0CE1 ED42 02012 SBC HL,BC ; from the CRTSIZE for
0CE3 EB 02013 EX DE,HL ; each protected line
0CE4 3D 02014 DEC A ;Dec scroll protect
0CE5 20F7 02015 JR NZ,$N4 ;Loop until done
0CE7 D5 02016 PUSH DE ;Save the move length
0CE8 E5 02017 PUSH HL ;Save the move-from
0CE9 ED42 02018 SBC HL,BC ;Move start back one
0CEB EB 02019 EX DE,HL ; line, Source =
0CEC E1 02020 POP HL ; start + one
0CED C1 02021 POP BC ;Get back dest locn
0CEE EDB0 02022 LDIR ;Scroll unprotected
0CF0 C1 02023 POP BC ;Recover line size
0CF1 182C 02024 JR CLREOF1 ;Clear to EOF from DE
02025 ;
02026 ; Set scroll protect value
02027 ; C = scroll protect <0-7>
02028 ; B = 7
02029 ; SVC = 15, @VDCTL
02030 ;
02031 SET_SCROLL
0CF3 79 02032 LD A,C ;Get user value
0CF4 E607 02033 AND 7 ;Make modulo 8
0CF6 4F 02034 LD C,A
0CF7 3A940B 02035 LD A,(DODATA$) ;P/u current mask
0CFA E6F8 02036 AND 0F8H ;Remove current scroll
0CFC B1 02037 OR C ;Merge in the new value
0CFD 32940B 02038 SETMASK LD (DODATA$),A ; & reload mask
0D00 AF 02039 XOR A ;Z-flag return
0D01 C9 02040 RET
02041 ;
02042 ; Routine to move down one line {10/13}
02043 ;
0D02 CDF80B 02044 LINFEED CALL CRSBOL ;Move to BOL
0D05 D5 02045 PUSH DE ;Save cursor position
0D06 CD300C 02046 CALL CRSDOWN ;Move down one line
0D09 B7 02047 OR A ;Reset the carry flag
0D0A 2180FF 02048 LD HL,CRTEND+1 ; & check if off of
0D0D ED52 02049 SBC HL,DE ; the screen
0D0F 28BD 02050 JR Z,DO_SCROLL ;Scroll if so
0D11 E1 02051 POP HL ;Discard old position
0D12 D5 02052 CLREOL PUSH DE ;Save new cursor pos
0D13 CDF80B 02053 CALL CRSBOL ;Get start of line
0D16 214F00 02054 LD HL,79 ;Calculate end of line
0D19 19 02055 ADD HL,DE ;HL = end of line
0D1A D1 02056 POP DE ;DE = current position
0D1B D5 02057 PUSH DE
0D1C 1804 02058 JR CLREOF2 ;Clear the line
02059 ;
02060 ; Clear to the end of the frame
02061 ;
0D1E D5 02062 CLREOF PUSH DE ;Save current cursor pos
0D1F 217FFF 02063 CLREOF1 LD HL,CRTEND ;Point to last RAM byte
0D22 3ACB0D 02064 CLREOF2 LD A,(INVIDEO) ;P/u normal/reverse
0D25 CBEF 02065 SET 5,A ; & make it a space
0D27 12 02066 LD (DE),A ;Stuff the "space"
0D28 B7 02067 OR A ;Reset carry for subtract
0D29 ED52 02068 SBC HL,DE ;Calculate length
0D2B 2809 02069 JR Z,CLREOF3 ;Back if at end already
0D2D C5 02070 PUSH BC
0D2E 44 02071 LD B,H ;Xfer length to BC
0D2F 4D 02072 LD C,L
0D30 62 02073 LD H,D ;Xfer start to HL
0D31 6B 02074 LD L,E
0D32 13 02075 INC DE ;Bump up by one
0D33 EDB0 02076 LDIR ;Propagate the space
0D35 C1 02077 POP BC
0D36 D1 02078 CLREOF3 POP DE
0D37 C9 02079 RET
02080 ;
02081 ; Routine to stuff the video cursor RAM address
02082 ;
0D38 CDD00D 02083 @VDCTL3 CALL ROWCOL_2_ADDR ;Calculate video address
0D3B C0 02084 RET NZ ;Back on error
0D3C F3 02085 DI ;Disable any video tasks
0D3D ED53950B 02086 LD (CURSOR),DE ; until cursor is updated
0D41 C9 02087 RET
02088 ;
02089 ; Video control SVC processor
02090 ;
02091 @_VDCTL
0D42 CD1708 02092 CALL ENADIS_DO_RAM ;Bring up the video RAM
02093 ;
02094 ; Test if in Task processor
02095 ;
0D45 3A7700 02096 LD A,(NFLAG$) ;P/u NFLAG$
0D48 CB77 02097 BIT 6,A ;Test for task process
0D4A 2015 02098 JR NZ,VDCTL ;If so skip setup
02099 ;
02100 ; HANDLES @VDCTL screen set up for normal use
02101 ;
0D4C D5 02102 PUSH DE
0D4D CDB30D 02103 CALL $N0 ;Normalize character at cursor
0D50 D1 02104 POP DE ;Recover value
0D51 D5 02105 PUSH DE
0D52 CD610D 02106 CALL VDCTL ;Do function request
0D55 F5 02107 PUSH AF ;Save the error status
0D56 F3 02108 DI ;Stop video tasks tempy
0D57 ED5B950B 02109 LD DE,(CURSOR)
0D5B CDCC0B 02110 CALL DO_RET1 ;Normalize screen and cursor
0D5E F1 02111 POP AF
0D5F D1 02112 POP DE
0D60 C9 02113 RET
02114 ;
0D61 3E09 02115 VDCTL LD A,9 ;Check for VIDLINE,
0D63 B8 02116 CP B ; function 9
0D64 2825 02117 JR Z,VIDLIN
0D66 3E2B 02118 LD A,43 ;Prepare for user ERROR
0D68 05 02119 DEC B
0D69 2843 02120 JR Z,GET_@_ROWCOL ; from row-H, col-L
0D6B 05 02121 DEC B
0D6C 2858 02122 JR Z,PUT_@_ROWCOL ; to row-H, col-L
0D6E 05 02123 DEC B
0D6F 28C7 02124 JR Z,@VDCTL3 ;Set cursor to H,L
0D71 05 02125 DEC B
0D72 287D 02126 JR Z,ADDR_2_ROWCOL ;Cursor row,col to H,L
0D74 1100F8 02127 LD DE,CRTBGN$ ;Init to start of video
0D77 05 02128 DEC B
0D78 282D 02129 JR Z,VIDMOV1 ;User RAM to video
0D7A 05 02130 DEC B
0D7B 2822 02131 JR Z,VIDMOVE ;Video RAM to user
0D7D 05 02132 DEC B
0D7E CAF30C 02133 JP Z,SET_SCROLL ;Set scroll protect
0D81 05 02134 DEC B
0D82 C0 02135 RET NZ ;Return if bad request
02136 ;
02137 ; Establish cursor character
02138 ;
0D83 E5 02139 PUSH HL
0D84 21980B 02140 LD HL,CRSCHAR ;Point to cursor char storage
0D87 7E 02141 LD A,(HL) ;P/u current cursor character
0D88 71 02142 LD (HL),C ; & update with new one
0D89 E1 02143 POP HL
0D8A C9 02144 RET
02145 ;
02146 ; VIDLIN routine function - 9 in register B
02147 ;
0D8B 2E00 02148 VIDLIN LD L,0 ;Always starts at col 0
0D8D D5 02149 PUSH DE ;Save user buffer
0D8E CDD00D 02150 CALL ROWCOL_2_ADDR ;Get address to DE
0D91 E1 02151 POP HL ;Recover user buffer
0D92 C0 02152 RET NZ ;Quit on bad address
0D93 0C 02153 INC C ;Check direction
0D94 0D 02154 DEC C ;If Z then to screen
0D95 2801 02155 JR Z,MOVLIN ;Set to go
0D97 EB 02156 EX DE,HL ;Reverse direction
0D98 015000 02157 MOVLIN LD BC,LINESIZ ;Set line size
0D9B EDB0 02158 LDIR ;Move it
0D9D AF 02159 XOR A ;Z on RET
0D9E C9 02160 RET
02161 ;
02162 ; Routine to move video RAM
02163 ;
0D9F 7C 02164 VIDMOVE LD A,H ;Check on user buffer
0DA0 C608 02165 ADD A,8 ; not above X'F800' &
0DA2 FE2C 02166 CP 24H+8 ; not below X'2400'
0DA4 3847 02167 JR C,PERR
0DA6 EB 02168 EX DE,HL ;Xchng user buffer,screen
0DA7 018007 02169 VIDMOV1 LD BC,CRTSIZE ;Set for full screen xfer
0DAA EDB0 02170 LDIR
0DAC BF 02171 CP A ;Set Z flag
0DAD C9 02172 RET
02173 ;
02174 ; Routine to get the character at row,col
02175 ;
02176 GET_@_ROWCOL
0DAE CDD00D 02177 CALL ROWCOL_2_ADDR ;Get Address of req
0DB1 1A 02178 LD A,(DE) ;P/u the character
0DB2 C9 02179 RET ;Back on error or no error
02180 ;
02181 ; Routine to halt blinking cursor & restore char
02182 ;
0DB3 E5 02183 $N0 PUSH HL
0DB4 217F00 02184 LD HL,VFLAG$
0DB7 CBFE 02185 SET 7,(HL) ;Disable blinking cursor
0DB9 E1 02186 POP HL
0DBA ED5B950B 02187 LD DE,(CURSOR) ;Get cursor pos in DE
0DBE 3A970B 02188 LD A,(CRSAVE) ;P/u saved character
0DC1 B7 02189 OR A ;If one is saved, put
02190 ; it on screen, else
0DC2 2009 02191 JR NZ,PUTA@DE ; ignore it
0DC4 1A 02192 LD A,(DE) ;Cursor not ON but get
0DC5 C9 02193 RET ; character anyway
02194 ;
02195 ; Routine to put a character at row,col
02196 ;
02197 PUT_@_ROWCOL
0DC6 CDD00D 02198 CALL ROWCOL_2_ADDR ;Get address of req
0DC9 C0 02199 RET NZ ;Back on error
0DCA 3E00 02200 PUT_@ LD A,0 ;Merge in reverse video
0DCB 02201 INVIDEO EQU $-1
0DCC B1 02202 OR C
0DCD 12 02203 PUTA@DE LD (DE),A ;Put the character
0DCE BF 02204 CP A ;Set Z-flag for return
0DCF C9 02205 RET
02206 ;
02207 ; Routine to calculate cursor position from row,col
02208 ;
02209 ROWCOL_2_ADDR
0DD0 3E4F 02210 LD A,79
0DD2 BD 02211 CP L
0DD3 3818 02212 JR C,PERR ;Error if > 79
0DD5 7C 02213 LD A,H ;P/u row number
0DD6 FE18 02214 CP 24
0DD8 3013 02215 JR NC,PERR ;Error if > 23
0DDA E5 02216 PUSH HL
0DDB C5 02217 PUSH BC
0DDC 4D 02218 LD C,L ;Save column
0DDD 06F8 02219 LD B,CRTBGN$<-8 ;Set to start of DO RAM
0DDF 215000 02220 LD HL,LINESIZ
0DE2 CDC906 02221 CALL @MUL16 ;Rows * line size
0DE5 65 02222 LD H,L ;Shift to HL
0DE6 6F 02223 LD L,A
0DE7 09 02224 ADD HL,BC ;Add in col & RAM start
0DE8 EB 02225 EX DE,HL ;Address to DE
0DE9 C1 02226 POP BC
0DEA E1 02227 POP HL
0DEB AF 02228 XOR A ;Set Z flag
0DEC C9 02229 RET
0DED 3E2B 02230 PERR LD A,43 ;SVC parameter error
0DEF B7 02231 OR A ;Set NZ condition
0DF0 C9 02232 RET
02233 ;
02234 ; Routine to get row,col of video cursor
02235 ;
02236 ADDR_2_ROWCOL
0DF1 2A950B 02237 LD HL,(CURSOR) ;Get addr in HL
0DF4 7C 02238 ADDR1 LD A,H ;Make address relative
0DF5 E607 02239 AND 7 ; to origin 0
0DF7 67 02240 LD H,A
0DF8 3E50 02241 LD A,LINESIZ ;Set divisor
0DFA CDE306 02242 CALL @DIV16
0DFD 65 02243 LD H,L ;Row to register H
0DFE 6F 02244 LD L,A ;Column to register L
0DFF AF 02245 XOR A ;Set zero return code
0E00 C9 02246 RET
0E00 02247 DOEND EQU $-1
0E01 02249 *GET PRDVR:3 ;Printer driver & filter
02250 ;PRDVR/ASM - LS-DOS 6.2
02253 *MOD
00F8 02254 PRPORT EQU 0F8H
02255 ;
02256 ; PR driver entry point
02257 ; It passes X'00'-X'FF'
02258 ; Unless INTL version
02259 ;
0E01 180A 02260 PRDVR JR PRBGN ;Branch around linkage
0E03 3C0E 02261 DW PREND ;Last byte used
0E05 03 02262 DB 3,'$PR'
24 50 52
0E09 1802 02263 DW PRDCB$ ;Pointer to its DCB
0E0B 0000 02264 DW 0 ;Reserved
02265 ;
02266 ; Driver code
02267 ;
0E0D 280A 02268 PRBGN JR Z,$O2 ;Go if output
0E0F 3804 02269 JR C,$O1 ;Go if input req
02270 ;
02271 ; Character CTL request
02272 ;
0E11 79 02273 LD A,C ;If CTL 0, return
0E12 B7 02274 OR A ; status else
0E13 2821 02275 JR Z,$O4 ; treat as a Get
02276 ;
02277 ; Character GET request
02278 ;
0E15 F6FF 02279 $O1 OR 0FFH ;Set nz
0E17 2F 02280 CPL ; & A=0 to show
0E18 C9 02281 RET ; no char available
02282 ;
02283 ; Character PUT request
02284 ;
0E19 11FFFF 02285 $O2 LD DE,0FFFFH ;Check status 2000 times
0E1C CD360E 02286 $O2A CALL $O4 ;PR ready?
0E1F 2811 02287 JR Z,$O3 ;Go if so
02288 ;
02289 ; Ten second timout delay loop
02290 ;
0E21 C5 02291 PUSH BC ;Printer was not ready
0E22 010800 02292 LD BC,8
0E25 CD8203 02293 CALL PAUSE@ ;Delay a bit
0E28 C1 02294 POP BC
02295 IF @BLD631
0E29 1B 02296 @PRTIMO:DEC DE ;<631>SYSTEM cmd patches this addr
02297 ELSE
02298 DEC DE ;Time up?
02299 ENDIF
0E2A 7A 02300 LD A,D
0E2B B3 02301 OR E
0E2C 20EE 02302 JR NZ,$O2A ;Nope, continue check
0E2E 3E08 02303 LD A,8 ;Device not avail...
0E30 B7 02304 OR A ;Set NZ condition
0E31 C9 02305 RET
0E32 02306 $O3 EQU $
02307 ;
02308 IF @INTL
02309 LD A,(IFLAG$)
02310 BIT 6,A ;Special DMP PR?
02311 ENDIF
02312 ;
0E32 79 02313 LD A,C