[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_2011 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 02314 ; 02315 IF @INTL 02316 JR Z,PVAL3 02317 CP 0C0H ;Values C0-FF (-20H) 02318 JR C,PVAL2 ;Go if less 02319 SUB 20H ;Shift to European chars 02320 JR PVAL3 02321 PVAL2 CP 0A0H ;A0-BF (+40H) 02322 JR C,PVAL3 ;Go if less 02323 ADD A,40H ;Shift to graphics 02324 ENDIF 02325 ; 0E33 D3F8 02326 PVAL3 OUT (PRPORT),A ;Put out char 02327 ; 02328 IF @INTL 02329 LD A,C ;Restore original 02330 CP A ;Set Z 02331 ENDIF 02332 ; 0E35 C9 02333 RET 02334 ; 0E36 DBF8 02335 $O4 IN A,(PRPORT) ;Scan PR status 0E38 E6F0 02336 AND 0F0H ;Mask unused positions 0E3A FE30 02337 CP 30H ;PR ready? 0E3C C9 02338 RET ;Return with answer 0E3C 02339 PREND EQU $-1 0E3D 02340 *GET FDCDVR:3 ;Floppy disk driver 02341 ;FDCDVR/ASM - LS-DOS 6.2 02344 ; 02345 ; HL=> buffer address 02346 ; D=> track desired 02347 ; E=> sector desired 02348 ; C=> drive desired 02349 ; B=> disk primitive command 02350 ; 00E4 02351 WRNMIPORT EQU 0E4H ;NMI mask register 00F0 02352 FDCADR EQU 0F0H ;FDC command 00F0 02353 FDCSTAT EQU 0F0H ;FDC status 00F1 02354 TRKREG EQU 0F1H ;FDC track register 00F2 02355 SECREG EQU 0F2H ;FDC sector register 00F3 02356 DATREG EQU 0F3H ;FDC data register 00F4 02357 DSELCT EQU 0F4H ;Drive select port 02358 ; 02359 ; 02360 ; Disk Driver Entry Point 02361 ; 0E3D 184F 02362 FDCDVR JR FDCBGN ;Branch to entry code 0E3F F30F 02363 DW FDCEND ;Last byte used 0E41 03 02364 DB 3,'$FD' ;Module name 24 46 44 02365 ; 02366 ; Automatic density recognition and retry density switch 02367 ; 02368 SWDEN 0E45 3E03 02369 LD A,3 ;Check counter for 2 0E47 B8 02370 CP B ; tries left after this one 0E48 285E 02371 JR Z,RESTOR ;If so try a RESTORE 02372 ; 0E4A FD7E03 02373 LD A,(IY+3) ;Flip the density bit, 0E4D EE40 02374 XOR 40H ; Bit 6, (IY+3) 0E4F FD7703 02375 LD (IY+3),A 0E52 010924 02376 LD BC,2409H ;Set alloc to SDEN 0E55 CB77 02377 BIT 6,A ;Test SDEN/DDEN 0E57 2803 02378 JR Z,SDEN ;Do SDEN if it was DDEN 0E59 011145 02379 LD BC,4511H ; else set alloc to DDEN 0E5C FD7107 02380 SDEN LD (IY+7),C 0E5F FD7008 02381 LD (IY+8),B 0E62 C9 02382 RET 02383 ; 02384 ; Verify routine 02385 ; 0E63 21E80F 02386 VERFIN LD HL,BUCKET ;Set byte bucket 0E66 3E2D 02387 LD A,2DH ;Set for DEC L,... 0E68 1E 02388 DB 1EH ;Ignore next with LD E,n 02389 ; 02390 ; Read routine 02391 ; 0E69 AF 02392 RDIN XOR A ;Set for NOP 0E6A 327D0E 02393 LD (CKVER),A 0E6D CD2B0F 02394 CALL RWINIT ;Initialize 0E70 1E16 02395 LD E,16H ;Status mask 0E72 DBF0 02396 RDIN1 IN A,(FDCSTAT) ;Get status 0E74 A3 02397 AND E ;Loop until DRQ 0E75 28FB 02398 JR Z,RDIN1 ; or error 0E77 EDA2 02399 INI ;Grab byte 0E79 F3 02400 DI 0E7A 7A 02401 LD A,D ;Get drive sel + WSGEN 0E7B D3F4 02402 RDIN2 OUT (DSELCT),A ;Initiate wait state 0E7D 00 02403 CKVER NOP ;DEC L: if verify 0E7E EDA2 02404 INI ;Xfer byte 0E80 20F9 02405 JR NZ,RDIN2 ;Loop then TSTBSY 02406 ; 02407 ; Reselect drive while controller is busy 02408 ; 0E82 DBF0 02409 TSTBSY IN A,(FDCSTAT) ;Ck FDC status 0E84 CB47 02410 BIT 0,A ;Busy? 0E86 C8 02411 RET Z ;RET if not 0E87 3A1B00 02412 LD A,(PDRV$) ;P/u drive 0E8A D3F4 02413 OUT (DSELCT),A ; & reselect 0E8C 18F4 02414 JR TSTBSY ;Loop until idle 02415 ; 02416 ; Driver start 02417 ; 0E8E 78 02418 FDCBGN LD A,B ;P/u primitive request 0E8F A7 02419 AND A ;NOP? 0E90 C8 02420 RET Z ;Quit if so 0E91 FE07 02421 CP 7 0E93 28ED 02422 JR Z,TSTBSY ;Jump on TSTBSY request 0E95 D2440F 02423 JP NC,IORQST ;Jump on I/O request 0E98 FE06 02424 CP 6 0E9A 284C 02425 JR Z,SEEKTRK ;Jump on track seek 0E9C 3D 02426 DEC A 0E9D 2811 02427 JR Z,SELECT ;Jump on drive select 0E9F FD3405 02428 INC (IY+5) ;Bump current cylinder 0EA2 FE04 02429 CP 4 0EA4 0658 02430 LD B,58H ;FDC step-in command 0EA6 2872 02431 JR Z,STEPIN 0EA8 FD360500 02432 RESTOR LD (IY+5),0 ;Set track to 0 0EAC 0608 02433 LD B,8 ;Restore drive 0EAE 186A 02434 JR STEPIN 02435 ; 0EB0 CD820E 02436 SELECT CALL TSTBSY ;Check drive status 0EB3 07 02437 RLCA 02438 IF @BLD631 02439 ; 02440 ; This is the first part of the fix for Gate-Array systems. Provided 02441 ; by Frank Durda IV in a paper for The Misosys Quarterly, Vol IV.iii 02442 ; Essentially, the motor-on timer in gate-array Model 4/4D/4P systems 02443 ; sometimes fails to log a write to 0xD4, and the motor can unexpectedly 02444 ; spin-down. The most common symptom is to end up with duplicate 02445 ; directory entries. The patch ensures that for directory accesses 02446 ; port 0xd4 is accessed twice before read/write operations begin. 02447 ; 0EB4 FD7E03 02448 LD A,(IY+3) ;<631>P/u SDEN/DDEN/DELAY (DLY chked later) 0EB7 F5 02449 PUSH AF ;<631>Save NOT READY flag 0EB8 C5 02450 PUSH BC ;<631> 02451 ELSE 02452 PUSH AF ;Save NOT READY flag 02453 PUSH BC 02454 LD A,(IY+3) ;P/u SDEN/DDEN 02455 ENDIF 0EB9 17 02456 RLA ;Bit 6=>7, bit 4=>4 0EBA CB2F 02457 SRA A 0EBC E690 02458 AND 90H ;Keep only DDEN & side 1 0EBE 4F 02459 LD C,A ;Save the bits 0EBF CB7F 02460 BIT 7,A ;Check if SDEN or DDEN 0EC1 2808 02461 JR Z,NOPCMP ;No precomp if SDEN 0EC3 FD7E09 02462 LD A,(IY+9) ;Set precomp on all 0EC6 BA 02463 CP D ; tracks above DIR 0EC7 3002 02464 JR NC,NOPCMP ;Go if no precomp needed 0EC9 CBE9 02465 SET 5,C ;Request precomp 0ECB FD7E04 02466 NOPCMP LD A,(IY+4) ;Get drive sel code 0ECE E60F 02467 AND 0FH ;Keep only sel bits 0ED0 B1 02468 OR C ;Merge in bits 4,5,7 0ED1 C1 02469 POP BC 0ED2 D3F4 02470 OUT (DSELCT),A ;Select drive 0ED4 321B00 02471 LD (PDRV$),A ;Store port byte 02472 IF @BLD631 02473 ; This is the second part of the fix for Gate-Array systems. Provided 02474 ; by Frank Durda IV in a paper for The Misosys Quarterly, Vol IV.iii 0ED7 D3F4 02475 OUT (DSELCT),A ;<631>Re-write Drive select just in case 0ED9 F1 02476 POP AF ;<631>Retrieve Not Ready Bit 0EDA D0 02477 RET NC ;<631>Return if was ready 0EDB CB57 02478 BIT 2,A ;<631>Check DELAY=0.5 or 1.0 (IY+3 in A) 02479 ELSE 02480 POP AF ;Retrieve Not Ready bit 02481 RET NC ;Ret if was ready 02482 BIT 2,(IY+3) ;Check DELAY=0.5 or 1.0 02483 ENDIF 0EDD CCE00E 02484 CALL Z,FDCDLY ;Double delay if 1.0 0EE0 C5 02485 FDCDLY PUSH BC ;Delay routine 0EE1 067F 02486 LD B,7FH 0EE3 CD8203 02487 CALL PAUSE@ 0EE6 C1 02488 POP BC 0EE7 C9 02489 RET 02490 ; 02491 ; Routine to seek a track 02492 ; 0EE8 CD820E 02493 SEEKTRK CALL TSTBSY ;Wait till not busy 0EEB FD7E05 02494 LD A,(IY+5) ;P/u current cylinder 0EEE D3F1 02495 OUT (TRKREG),A ; & set FDC to current 0EF0 FD7E07 02496 LD A,(IY+7) ;P/u alloc data 0EF3 E61F 02497 AND 1FH ;Get highest # sector 0EF5 93 02498 SUB E ;Form req sector minus 0EF6 2F 02499 CPL ; max, setting CY flag if 0EF7 FDCB03A6 02500 RES 4,(IY+3) ; init side select to 0 0EFB 300B 02501 JR NC,SETSECT ;Go if sector on side 0 0EFD FDCB046E 02502 BIT 5,(IY+4) ;If not 2-sided media, 0F01 2806 02503 JR Z,FRCSID0 ; don't set side 1 0F03 FDCB03E6 02504 SET 4,(IY+3) ;Set side 1 0F07 06 02505 DB 06H ;Ignore next with LD B,n 0F08 7B 02506 SETSECT LD A,E ;Restore unaltered sec # 0F09 D3F2 02507 FRCSID0 OUT (SECREG),A ;Set sector 0F0B 7A 02508 LD A,D 0F0C D3F3 02509 OUT (DATREG),A ;Set desired track 0F0E FDBE05 02510 CP (IY+5) ;If at desired track, 0F11 0618 02511 LD B,18H ; use seek, else use 0F13 2805 02512 JR Z,STEPIN ; seek w/verify 0F15 FD7205 02513 LD (IY+5),D ;Update current cylinder 0F18 061C 02514 LD B,1CH ;Seek w/verify ocmmand 0F1A CDB00E 02515 STEPIN CALL SELECT ;Select drive 0F1D FD7E03 02516 LD A,(IY+3) 0F20 E603 02517 AND 3 ;Strip all but step rate 0F22 B0 02518 OR B 0F23 D3F0 02519 PASSCMD OUT (FDCADR),A ;Give FDC its command 0F25 0612 02520 LD B,12H 0F27 10FE 02521 DJNZ $ ;Wait 0F29 AF 02522 XOR A 0F2A C9 02523 FDCRET RET 02524 ; 02525 ; Read and write init routines 02526 ; 0F2B 7A 02527 RWINIT LD A,D ;Restuff trk reg 0F2C D3F1 02528 OUT (TRKREG),A 0F2E 3A1B00 02529 LD A,(PDRV$) ;Get select code 0F31 F640 02530 OR 40H ;Set WSGEN bit 0F33 57 02531 LD D,A ;Save code in D 0F34 E610 02532 AND 10H ;Get side sel bit 0F36 0F 02533 RRCA ; to bit 3 0F37 CB49 02534 BIT 1,C ;Check if doing side cmp 0F39 2001 02535 JR NZ,GETCMD ;Go if so 0F3B AF 02536 XOR A 0F3C B1 02537 GETCMD OR C 0F3D 0EF3 02538 LD C,DATREG ;Get port into C 0F3F CD0E00 02539 CALL FDDINT$ ;Interrupts on or off? 0F42 18DF 02540 JR PASSCMD ;Pass command to ctrlr 02541 ; 02542 ; I/O request handler 02543 ; 0F44 CB50 02544 IORQST BIT 2,B ;Write command? 0F46 ED4B7A00 02545 LD BC,(RFLAG$-1) ;P/u retry count 0F4A 0E82 02546 LD C,82H ;FDC cmd=readsec 0F4C 2010 02547 JR NZ,WRCMD ;Go if write command 0F4E FE0A 02548 CP 10 ;Verify sector? 0F50 2806 02549 JR Z,VERFY 0F52 CD790F 02550 CALL GRABNDO ;Grab next code & insert 0F55 01 02551 DB 1 ;Error code start 0F56 690E 02552 DW RDIN ;Read entry point 0F58 CD790F 02553 VERFY CALL GRABNDO ;Stuff I/O direction 0F5B 01 02554 DB 1 ;Error code start 0F5C 630E 02555 DW VERFIN ;Verify entry point 0F5E FDCB037E 02556 WRCMD BIT 7,(IY+3) ;Software WP? 0F62 2803 02557 JR Z,WRCMD1 ;Bypass if not 0F64 3E0F 02558 LD A,15 ;Else set WP error 0F66 C9 02559 RET 0F67 0EA2 02560 WRCMD1 LD C,0A2H ;Write sector FDC command 0F69 FE0E 02561 CP 14 ;Directory sector? 0F6B 3806 02562 JR C,DOWRIT 0F6D 0EA3 02563 LD C,0A3H ;Change DAM if directory 0F6F 2802 02564 JR Z,DOWRIT 0F71 0EF0 02565 LD C,0F0H ; else write track 0F73 CD790F 02566 DOWRIT CALL GRABNDO ;Switch code 0F76 09 02567 DB 9 ;Error code start 0F77 BC0F 02568 DW WROUT ;Write entry point 02569 ; 02570 ; Routine stuffs error start byte & I/O vector 02571 ; 0F79 E3 02572 GRABNDO EX (SP),HL ;Save HL & get ret addr 0F7A 7E 02573 LD A,(HL) ;P/u & stuff error code 0F7B 23 02574 INC HL ; start byte 0F7C 32B50F 02575 LD (ERRSTRT+1),A 0F7F 7E 02576 LD A,(HL) ;Set up data transfer 0F80 23 02577 INC HL ; direction vector 0F81 66 02578 LD H,(HL) 0F82 6F 02579 LD L,A 0F83 22930F 02580 LD (CALLIO),HL ;Stuff CALL vector 0F86 E1 02581 POP HL ;Restore buffer addr 02582 ; 02583 ; Main I/O handler routine 02584 ; 0F87 C5 02585 RETRY PUSH BC ;Save retry & FDC command 0F88 D5 02586 PUSH DE ;Save track/sector 0F89 E5 02587 PUSH HL ;Save buffer 0F8A CB61 02588 BIT 4,C ;Test for track command 0F8C CCE80E 02589 CALL Z,SEEKTRK ;Seek if not track write 0F8F CD820E 02590 CALL TSTBSY ;Wait till not busy 0F92 CD0000 02591 CALL 0 ;Call I/O routine 0F93 02592 CALLIO EQU $-2 ;Data xfer direction 0F95 00 02593 DISKEI NOP ;Will be changed to a EI after 02594 ; BOOT has read in SYS0 0F96 DBF0 02595 IN A,(FDCSTAT) ;Get status 0F98 E67C 02596 AND 7CH ;Strip all but 2-6 0F9A E1 02597 POP HL 0F9B D1 02598 POP DE ;Rcvr track & sector 0F9C C1 02599 POP BC ;Rcvr retry count & cmd 0F9D C8 02600 RET Z ;Ret if no error 0F9E CB57 02601 BIT 2,A ;Lost data? 0FA0 20E5 02602 JR NZ,RETRY ;Don't count this retry 0FA2 F5 02603 PUSH AF 0FA3 E618 02604 AND 18H ;Record not found or CRC 0FA5 280B 02605 JR Z,DISKDUN ;No retries if otherwise 0FA7 CB67 02606 BIT 4,A ;Record not found? 0FA9 C5 02607 PUSH BC ;If so, switch 0FAA C4450E 02608 CALL NZ,SWDEN ; density or restore 0FAD C1 02609 POP BC 0FAE F1 02610 POP AF 0FAF 10D6 02611 DJNZ RETRY ;Count down retry 0FB1 06 02612 DB 6 ;Ignore next with "LD B,nn" 0FB2 F1 02613 DISKDUN POP AF ;Adjust ret code 0FB3 47 02614 LD B,A 0FB4 3E00 02615 ERRSTRT LD A,0 ;Start with R=1, W=9 0FB6 CB08 02616 ERRTRAN RRC B 0FB8 D8 02617 RET C 0FB9 3C 02618 INC A 0FBA 18FA 02619 JR ERRTRAN 02620 ; 02621 ; Write routine 02622 ; 0FBC CD2B0F 02623 WROUT CALL RWINIT ;Set up initialization 0FBF 1E76 02624 LD E,76H ;Status mask 0FC1 DBF0 02625 WRO1 IN A,(FDCSTAT) ;P/u status 0FC3 A3 02626 AND E ;Fall out on DRQ or error 0FC4 28FB 02627 JR Z,WRO1 ; else loop 0FC6 EDA3 02628 OUTI ;Xfer byte to FDC 0FC8 F3 02629 DI ;Now kill the interrupts 0FC9 DBF0 02630 IN A,(FDCSTAT) ;Check for errors 0FCB 1F 02631 RRA ;Did BUSY drop? 0FCC D0 02632 RET NC ;Quit now if so 0FCD 3EC0 02633 LD A,0C0H ;Enable INTRQ and timeout 0FCF D3E4 02634 OUT (WRNMIPORT),A 0FD1 0650 02635 LD B,50H ;Time delay for WRSEC 0FD3 10FE 02636 DJNZ $ 0FD5 46 02637 LD B,(HL) ;Get next byte early 0FD6 23 02638 INC HL 0FD7 7A 02639 WRO3 LD A,D ;Enable wait states 0FD8 D3F4 02640 OUT (DSELCT),A 0FDA DBF0 02641 IN A,(FDCSTAT) ;Check if timed out 0FDC A3 02642 AND E ;Loop back if it timed 0FDD 28F8 02643 JR Z,WRO3 ; out (must be WRTRK) 0FDF ED41 02644 OUT (C),B ;Pass 2nd byte 0FE1 7A 02645 LD A,D ;Get sel code + WSGEN bit 0FE2 D3F4 02646 WRO2 OUT (DSELCT),A ;Pass until FDC times out 0FE4 EDA3 02647 OUTI ; & generates NMI 0FE6 18FA 02648 JR WRO2 02649 IFEQ $&0FFH,0FFH 02650 ERR 'Warning... BUCKET position error 02651 ENDIF 0FE8 53 02652 BUCKET DB 'S' 02653 ; 0FE9 AF 02654 @RSTNMI XOR A ;NMI vectors here 0FEA D3E4 02655 OUT (WRNMIPORT),A ;Disable INTRQ & timeout 0FEC 016400 02656 LD BC,100 ;Need to wait a moment 0FEF CD8203 02657 CALL PAUSE@ ;Call pause 0FF2 E1 02658 POP HL ;Discard return 0FF3 C9 02659 RET 0FF3 02660 FDCEND EQU $-1 0FF4 02661 DVREND$ EQU $ ;Start of low I/O area, to 12FFH 02662 IFGT $,1200H+START$ 02663 ERR 'Drivers overflow available RAM 02664 ENDIF 1300 02665 ORG 1300H+START$ 1300 02666 @BYTEIO EQU $ 0000 02667 END 0000 is the transfer address 00000 Total errors
[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_2011 at nemesis.lonestar.org]