1: ;*=*=* 2: ; xtrshard/dct 3: ; Emulate hard disk in a Unix file under xtrs 4: ; 5: ; Copyright (c) 1998, Timothy Mann 6: ; 7: ; This software may be copied, modified, and used for any 8: ; purpose without fee, provided that (1) the above copyright 9: ; notice is retained, and (2) modified versions are clearly 10: ; marked as having been modified, with the modifier's name and 11: ; the date included. 12: ; 13: ; Created 1-10-98 14: ; Last modified on Wed May 17 00:08:52 PDT 2000 by mann 15: ;*=*=* 16: 17: 18: ; Number of drives to allow 19: 0008 ndrive equ 8 20: 21: 22: ; ASCII chars 23: 000A LF equ 10 24: 000D CR equ 13 25: 0003 ETX equ 3 26: 27: ; Model 4 SVC numbers 28: 0064 @high equ 100 29: 000A @dsply equ 10 30: 0065 @flags equ 101 31: 000C @logot equ 12 32: 0052 @gtdcb equ 82 33: 0053 @gtmod equ 83 34: 005D @div8 equ 93 35: 005B @mul16 equ 91 36: 0009 @keyin equ 9 37: 38: ; Model I/III hard addresses 39: 0125 m3flag$ equ 0125h ; 'I' in ROM on Model III 40: 447B @logot1 equ 447bh 41: 428A @logot3 equ 428ah 42: 4467 @dsply1 equ 4467h 43: 4467 @dsply3 equ 4467h 44: 4049 high$1 equ 4049h 45: 4411 high$3 equ 4411h 46: 4758 cflag$1 equ 4758h 47: 4758 cflag$3 equ 4758h 48: 4303 @icnfg1 equ 4303h 49: 421D @icnfg3 equ 421dh 50: 4B8F @mult1 equ 4b8fh 51: 444E @mult3 equ 444eh 52: 4B7B @divea1 equ 4b7bh 53: 4B7A @divea3 equ 4b7ah 54: 0040 @keyin1 equ 0040h 55: 0040 @keyin3 equ 0040h 56: 57: ; Emulator trap instructions in byte-reversed form 58: 32ED emt_read equ 32EDH 59: 33ED emt_write equ 33EDH 60: 34ED emt_lseek equ 34EDH 61: 35ED emt_strerror equ 35EDH 62: 3DED emt_ftruncate equ 3DEDH 63: 3EED emt_opendisk equ 3EEDH 64: 3FED emt_closedisk equ 3FEDH 65: 66: ; Constants for emt_opendisk 67: 0000 EO_RDONLY equ 00o 68: 0001 EO_WRONLY equ 01o 69: 0002 EO_RDWR equ 02o 70: 0040 EO_CREAT equ 0100o 71: 0080 EO_EXCL equ 0200o 72: 0200 EO_TRUNC equ 01000o 73: 0400 EO_APPEND equ 02000o 74: 75: ;*=*=* 76: ; Set origin to be safe on both LDOS 5 and 6 77: ;*=*=* 78: 6000 org 6000h 79: 80: ;*=*=* 81: ; Relocator for disk driver 82: ;*=*=* 83: 6000 ED537363 instal: ld (dct),de ;Save DCT address 84: 6004 3A0A00 ld a,(000ah) ;Determine TRS-80 model 85: 6007 FE40 cp 40h 86: 6009 C23661 jp nz,lsdos6 ;Model 4 (or other LS-DOS, I hope) 87: 600C 3A2501 ld a,(m3flag$) 88: 600F FE49 cp 'I' 89: 6011 CAA560 jp z,model3 ;Go if Model III 90: ;*=*=* 91: ; LDOS 5 Model I - See LS-DOS 6 version for comments 92: ;*=*=* 93: 6014 3ECD ld a,0cdh ;Insert Model I @LOGOT 94: 6016 324262 ld (logot),a 95: 6019 217B44 ld hl,@logot1 96: 601C 224362 ld (logot+1),hl 97: 601F 327B65 ld (domul),a ;Insert Model I MULT 98: 6022 218F4B ld hl,@mult1 99: 6025 227C65 ld (domul+1),hl 100: 6028 32FA65 ld (dodiv),a ;Insert Model I DIVEA 101: 602B 217B4B ld hl,@divea1 102: 602E 22FB65 ld (dodiv+1),hl 103: 6031 3E31 ld a,'1' ;Modify filename 104: 6033 325366 ld (hmod),a 105: 6036 219D62 ld hl,hello_ 106: 6039 CD6744 call @dsply1 107: 603C 3A5847 ld a,(cflag$1) 108: 603F CB5F bit 3,a ;System request? 109: 6041 CA3762 jp z,viaset 110: 6044 ED5B7363 ld de,(dct) 111: 6048 7A ld a,d ;DRIVE= must be specified 112: 6049 B3 or e 113: 604A CA3362 jp z,needdr 114: 604D 214A63 asku1: ld hl,unit_ ;Ask which unit number 115: 6050 CD6744 call @dsply1 116: 6053 217563 ld hl,unit 117: 6056 010001 ld bc,100h 118: 6059 CD4000 call @keyin1 119: 605C DA3F62 jp c,hitbrk 120: 605F C23F62 jp nz,hitbrk 121: 6062 3A7563 ld a,(unit) 122: 6065 FE30 cp '0' 123: 6067 38E4 jr c,asku1 124: 6069 FE38 cp '0'+ndrive 125: 606B 30E0 jr nc,asku1 126: 606D 2A4940 ld hl,(high$1) 127: 6070 CD7062 call xgtmod ;Module already loaded? 128: 6073 CAEF61 jp z,setdct 129: 6076 2A4940 ld hl,(high$1) 130: 6079 227163 ld (newend),hl 131: 607C 11E001 ld de,length 132: 607F 97 sub a 133: 6080 ED52 sbc hl,de 134: 6082 224940 ld (high$1),hl 135: 6085 CD4166 call dvrini 136: 6088 CD4962 call relo 137: 608B 3A0343 ld a,(@icnfg1) 138: 608E 323E66 ld (link),a 139: 6091 2A0443 ld hl,(@icnfg1+1) 140: 6094 223F66 ld (link+1),hl 141: 6097 213666 ld hl,dvrcfg 142: 6098 rx16 equ $-2 143: 609A 220443 ld (@icnfg1+1),hl 144: 609D 3EC3 ld a,0c3h 145: 609F 320343 ld (@icnfg1),a 146: 60A2 C3E161 jp move 147: ;*=*=* 148: ; LDOS 5 Model III 149: ;*=*=* 150: 60A5 model3: 151: 60A5 3ECD ld a,0cdh ;Insert Model III @LOGOT 152: 60A7 324262 ld (logot),a 153: 60AA 218A42 ld hl,@logot3 154: 60AD 224362 ld (logot+1),hl 155: 60B0 327B65 ld (domul),a ;Insert Model III MULT 156: 60B3 214E44 ld hl,@mult3 157: 60B6 227C65 ld (domul+1),hl 158: 60B9 32FA65 ld (dodiv),a ;Insert Model III DIVEA 159: 60BC 217A4B ld hl,@divea3 160: 60BF 22FB65 ld (dodiv+1),hl 161: 60C2 3E33 ld a,'3' ;Modify filename 162: 60C4 325366 ld (hmod),a 163: 60C7 219D62 ld hl,hello_ 164: 60CA CD6744 call @dsply3 165: 60CD 3A5847 ld a,(cflag$3) 166: 60D0 CB5F bit 3,a ;System request? 167: 60D2 CA3762 jp z,viaset 168: 60D5 ED5B7363 ld de,(dct) 169: 60D9 7A ld a,d ;DRIVE= must be specified 170: 60DA B3 or e 171: 60DB CA3362 jp z,needdr 172: 60DE 214A63 asku3: ld hl,unit_ ;Ask which unit number 173: 60E1 CD6744 call @dsply3 174: 60E4 217563 ld hl,unit 175: 60E7 010001 ld bc,100h 176: 60EA CD4000 call @keyin3 177: 60ED DA3F62 jp c,hitbrk 178: 60F0 C23F62 jp nz,hitbrk 179: 60F3 3A7563 ld a,(unit) 180: 60F6 FE30 cp '0' 181: 60F8 38E4 jr c,asku3 182: 60FA FE38 cp '0'+ndrive 183: 60FC 30E0 jr nc,asku3 184: 60FE 2A1144 ld hl,(high$3) 185: 6101 CD7062 call xgtmod ;Module already loaded? 186: 6104 CAEF61 jp z,setdct 187: 6107 2A1144 ld hl,(high$3) 188: 610A 227163 ld (newend),hl 189: 610D 11E001 ld de,length 190: 6110 97 sub a 191: 6111 ED52 sbc hl,de 192: 6113 221144 ld (high$3),hl 193: 6116 CD4166 call dvrini 194: 6119 CD4962 call relo 195: 611C 3A1D42 ld a,(@icnfg3) 196: 611F 323E66 ld (link),a 197: 6122 2A1E42 ld hl,(@icnfg3+1) 198: 6125 223F66 ld (link+1),hl 199: 6128 213666 ld hl,dvrcfg 200: 6129 rx17 equ $-2 201: 612B 221E42 ld (@icnfg3+1),hl 202: 612E 3EC3 ld a,0c3h 203: 6130 321D42 ld (@icnfg3),a 204: 6133 C3E161 jp move 205: 206: ;*=*=* 207: ; LS-DOS 6 208: ;*=*=* 209: 6136 3E34 lsdos6: ld a,'4' ;Modify filename 210: 6138 325366 ld (hmod),a 211: 613B 219D62 ld hl,hello_ 212: 613E 3E0A ld a,@dsply ;Display hello 213: 6140 EF rst 40 214: ;*=*=* 215: ; Check if entry from SYSTEM command. 216: ;*=*=* 217: 6141 3E65 ld a,@flags ;Get flags pointer into IY 218: 6143 EF rst 40 219: 6144 FD7E02 ld a,(iy+'C'-'A') ;Get CFLAG$ 220: 6147 CB5F bit 3,a ;System request? 221: 6149 CA3762 jp z,viaset 222: 614C ED5B7363 ld de,(dct) 223: 6150 7A ld a,d ;DRIVE= must be specified 224: 6151 B3 or e 225: 6152 CA3362 jp z,needdr 226: ;*=*=* 227: ; Ask which unit number 228: ;*=*=* 229: 6155 214A63 asku4: ld hl,unit_ ;Ask which unit number 230: 6158 3E0A ld a,@dsply 231: 615A EF rst 40 232: 615B 217563 ld hl,unit 233: 615E 010001 ld bc,100h 234: 6161 3E09 ld a,@keyin 235: 6163 EF rst 40 236: 6164 DA3F62 jp c,hitbrk 237: 6167 C23F62 jp nz,hitbrk 238: 616A 3A7563 ld a,(unit) 239: 616D FE30 cp '0' 240: 616F 38E4 jr c,asku4 241: 6171 FE38 cp '0'+ndrive 242: 6173 30E0 jr nc,asku4 243: ;*=*=* 244: ; Check if driver already loaded 245: ;*=*=* 246: 6175 117C64 ld de,modnam 247: 6178 3E53 ld a,@gtmod 248: 617A EF rst 40 249: 617B CAEF61 jp z,setdct ;Already loaded, skip loading 250: ;*=*=* 251: ; Obtain low memory driver pointer. Bizarre API here! 252: ;*=*=* 253: 617E 1E4B ld e,'K' ;Locate pointer to *KI DCB 254: 6180 1649 ld d,'I' ; via @GTDCB SVC 255: 6182 3E52 ld a,@gtdcb 256: 6184 EF rst 40 257: 6185 C22F62 jp nz,curdl ;No error unless KI clobbered! 258: 6188 2B dec hl ;Decrement to driver pointer 259: 6189 56 ld d,(hl) ;P/u hi-order of pointer, 260: 618A 2B dec hl ; decrement to and p/u 261: 618B 5E ld e,(hl) ; lo-order of pointer 262: ;*=*=* 263: ; Check if driver will fit into [(LCPTR), X'12FF'] 264: ;*=*=* 265: 618C E5 push hl ;Save address of pointer 266: 618D 21E001 ld hl,length ;New pointer will be 267: 6190 19 add hl,de ; pointer + LENGTH 268: 6191 54 ld d,h ;Save a copy in DE 269: 6192 5D ld e,l 270: 6193 010113 ld bc,1301h ;If > 1300H, driver won't fit 271: 6196 97 sub a ;Reset carry flag 272: 6197 ED42 sbc hl,bc 273: 6199 E1 pop hl ;Get back address of pointer 274: 619A 300A jr nc,usehi ;Go if driver won't fit 275: 619C 73 ld (hl),e ;Store new value of pointer 276: 619D 23 inc hl 277: 619E 72 ld (hl),d 278: 619F 1B dec de ;Last byte of driver goes here 279: 61A0 ED537163 ld (newend),de 280: 61A4 1816 jr dorelo 281: ;*=*=* 282: ; Put in high memory instead. 283: ;*=*=* 284: 61A6 210000 usehi: ld hl,0 ;Get current HIGH$ 285: 61A9 45 ld b,l 286: 61AA 3E64 ld a,@high 287: 61AC EF rst 40 288: 61AD C23B62 jp nz,nomem 289: 61B0 227163 ld (newend),hl ;Last byte of driver goes here 290: 61B3 11E001 ld de,length 291: 61B6 97 sub a ;Reset carry flag 292: 61B7 ED52 sbc hl,de ;Compute new HIGH$ 293: 61B9 3E64 ld a,@high ;Set new HIGH$ into the system 294: 61BB EF rst 40 295: ;*=*=* 296: ; Relocate internal references in driver. 297: ; HL = address for last byte of driver. 298: ;*=*=* 299: 61BC CD4166 dorelo: call dvrini ;Final driver init before move 300: 61BF CD4962 call relo 301: ;*=*=* 302: ; Link to @ICNFG (must follow address relocation and precede movement) 303: ;*=*=* 304: 61C2 3E65 ld a,@flags ;Get flags pointer into IY 305: 61C4 EF rst 40 306: 61C5 FD7E1C ld a,(iy+28) ;Copy current @ICNFG into LINK 307: 61C8 FD6E1D ld l,(iy+29) 308: 61CB FD661E ld h,(iy+30) 309: 61CE 323E66 ld (link),a 310: 61D1 223F66 ld (link+1),hl 311: 61D4 213666 ld hl,dvrcfg ;Get relocated init address 312: 61D5 rx10 equ $-2 313: 61D7 FD751D ld (iy+29),l ;Save in @ICNFG vector 314: 61DA FD741E ld (iy+30),h 315: 61DD FD361CC3 ld (iy+28),0c3h ;Insert JP opcode 316: ;*=*=* 317: ; Move driver into low or high memory. 318: ;*=*=* 319: 61E1 move: 320: 61E1 ED5B7163 ld de,(newend) ;Destination address 321: 61E5 215666 ld hl,dvrend ;Last byte of module 322: 61E8 01E001 ld bc,length ;Length of filter 323: 61EB EDB8 lddr 324: 61ED EB ex de,hl 325: 61EE 23 inc hl ;Bump to driver entry 326: ;*=*=* 327: ; Setup DCT (iy+5 to iy+9 are reset by ckopen if successful) 328: ;*=*=* 329: 61EF setdct: 330: 61EF FD2A7363 ld iy,(dct) 331: 61F3 FD3600C3 ld (iy),0c3h ;JP instruction (enable driver) 332: 61F7 FD7501 ld (iy+1),l ;Driver address 333: 61FA FD7402 ld (iy+2),h 334: 61FD FD36030C ld (iy+3),00001100b ;Flags: rigid, fixed, step rate 0 335: 6201 3A7563 ld a,(unit) 336: 6204 E60F and 0fh 337: 6206 F610 or 00010000b ;Flags: alien (=no index pulses), unit# 338: 6208 FD7704 ld (iy+4),a 339: 620B FD360500 ld (iy+5),0 ;LDOS undefined; we use as sec/cyl (0=256). 340: 620F FD3606C9 ld (iy+6),201 ;high cylinder number 341: 6213 FD3607FF ld (iy+7),11111111b ;high head # (111), high sec/trak (11111) 342: 6217 FD3608FF ld (iy+8),11111111b ;high gran # (111), high sec/gran (11111) 343: 621B FD3609FF ld (iy+9),0ffh ;Directory cylinder 344: ;*=*=* 345: ; Open file now so user can get error if any, and so geometry 346: ; is established as early as possible. 347: ;*=*=* 348: 621F CD9965 call ckopen 349: 6222 210000 ld hl,0 ;Successful completion 350: 6225 C8 ret z ;Fall thru if error 351: ;*=*=* 352: 6226 217763 uerror: ld hl,errbuf ;Unix error 353: 6229 010001 ld bc,256 354: 622C ED35 defw emt_strerror 355: 622E DD defb 0ddh 356: 622F 21D562 curdl: ld hl,curdl_ ;Other error 357: 6232 DD defb 0ddh 358: 6233 213063 needdr: ld hl,needdr_ 359: 6236 DD defb 0ddh 360: 6237 210663 viaset: ld hl,viaset_ 361: 623A DD defb 0ddh 362: 623B 21E862 nomem: ld hl,nomem_ 363: 623E DD defb 0ddh 364: 623F 216663 hitbrk: ld hl,hitbrk_ 365: 6242 3E0C logot: ld a,@logot 366: 6244 EF rst 40 367: 6245 21FFFF ld hl,-1 ;Unuccessful completion 368: 6248 C9 ret 369: 370: ;*=*=* 371: ; Relocate internal references in driver. 372: ; HL = address for last byte of driver. 373: ;*=*=* 374: 6249 2A7163 relo: ld hl,(newend) 375: 624C FD215766 ld iy,reltab ;Point to relocation tbl 376: 6250 115666 ld de,dvrend 377: 6253 97 sub a ;Clear carry flag 378: 6254 ED52 sbc hl,de 379: 6256 44 ld b,h ;Move to BC 380: 6257 4D ld c,l 381: 6258 FD6E00 rloop: ld l,(iy) ;Get address to change 382: 625B FD6601 ld h,(iy+1) 383: 625E 7C ld a,h 384: 625F B5 or l 385: 6260 C8 ret z 386: 6261 5E ld e,(hl) ;P/U address 387: 6262 23 inc hl 388: 6263 56 ld d,(hl) 389: 6264 EB ex de,hl ;Offset it 390: 6265 09 add hl,bc 391: 6266 EB ex de,hl 392: 6267 72 ld (hl),d ;And put back 393: 6268 2B dec hl 394: 6269 73 ld (hl),e 395: 626A FD23 inc iy 396: 626C FD23 inc iy 397: 626E 18E8 jr rloop ;Loop till done 398: 399: ;*=*=* 400: ; Search for existing copy of driver. 401: ; Rough Model I/III emulation of Model 4 @GTMOD, 402: ; hardcoded with driver address. 403: ; Entry: HL holds HIGH$ 404: ; Exit Z: HL holds driver address 405: ; NZ: driver not found 406: ;*=*=* 407: 6270 23 xgtmod: inc hl 408: 6271 7C ld a,h 409: 6272 B5 or l 410: 6273 2002 jr nz,xgtm1 411: 6275 3D dec a ;not found 412: 6276 C9 ret 413: 6277 7E xgtm1: ld a,(hl) 414: 6278 FE18 cp 18h ;unconditional jr? 415: 627A C0 ret nz ;not a module header 416: 627B E5 push hl ;save start address 417: 627C 23 inc hl ;skip jr 418: 627D 23 inc hl ;skip offset 419: 627E 23 inc hl ;skip start address 420: 627F 23 inc hl 421: 6280 7E ld a,(hl) ;compare name length 422: 6281 FE08 cp modptr-modnam 423: 6283 200F jr nz,nextmd ;different - skip 424: 6285 47 ld b,a ;compare name 425: 6286 117C64 ld de,modnam 426: 6289 23 inc hl 427: 628A 1A xgtm2: ld a,(de) 428: 628B BE cp (hl) 429: 628C 2006 jr nz,nextmd ;different - skip 430: 628E 13 inc de 431: 628F 23 inc hl 432: 6290 10F8 djnz xgtm2 433: 6292 E1 pop hl ;same - found 434: 6293 C9 ret 435: 6294 E1 nextmd: pop hl ;get back start of module 436: 6295 23 inc hl 437: 6296 23 inc hl 438: 6297 5E ld e,(hl) ;pointer to last byte 439: 6298 23 inc hl 440: 6299 56 ld d,(hl) 441: 629A EB ex de,hl 442: 629B 18D3 jr xgtmod 443: 444: ;*=*=* 445: ; Messages and globals 446: ;*=*=* 447: 629D 58545253 hello_: defb 'XTRSHARD - Emulated hard disk driver for xtrs - 5/17/00',CR 48415244 202D2045 6D756C61 74656420 68617264 20646973 6B206472 69766572 20666F72 20787472 73202D20 352F3137 2F30300D 448: 62D5 4C532D44 curdl_: defb 'LS-DOS is curdled!',CR 4F532069 73206375 72646C65 64210D 449: 62E8 48696768 nomem_: defb 'High memory is not available!',CR 206D656D 6F727920 6973206E 6F742061 7661696C 61626C65 210D 450: 6306 4D757374 viaset_:defb 'Must install via SYSTEM (DRIVE=,DRIVER=)!',CR 20696E73 74616C6C 20766961 20535953 54454D20 28445249 56453D2C 44524956 45523D29 210D 451: 6330 44524956 needdr_:defb 'DRIVE= must be specified!',CR 453D206D 75737420 62652073 70656369 66696564 210D 452: 634A 456E7465 unit_: defb 'Enter unit number ([0]-','0'+ndrive-1,'): ',ETX 7220756E 6974206E 756D6265 7220285B 305D2D37 293A2003 453: 6366 41626F72 hitbrk_:defb 'Aborted!',CR 74656421 0D 454: 636F 0000 lcptr: defw 0 455: 6371 0000 newend: defw 0 456: 6373 0000 dct: defw 0 457: 6375 unit: defs 2 458: 6377 errbuf: defs 256 459: 460: ; 461: ; Driver - Based on skeletal driver from the Guide 462: ; 463: 464: 6477 1827 entry: jr begin ;The driver starts with the 465: 6479 5666 defw dvrend ; DOS standard header 466: 6479 rx00 equ $-2 467: 647B 08 defb modptr-modnam ;Length of name 468: 647C 78747273 modnam: defb 'xtrshard' ;Name for @GTMOD requests 68617264 469: 6484 0000 modptr: defw 0 ;These pointers are unused 470: 6486 0000 defw 0 471: 6488 fd: defs ndrive*2 ;Unix file descriptors 472: 6498 00000000 offset: defw 0,0,0,0 ;lseek offset buffer 00000000 473: 64A0 begin: 474: ;*=*=* 475: ; First make sure the file is open and correct the geometry 476: ; in the DCT if needed. 477: ;*=*=* 478: 64A0 DDE5 push ix 479: 64A2 CD9965 call ckopen 480: 64A3 rx03 equ $-2 481: 64A5 CDAB64 call body 482: 64A6 rx06 equ $-2 483: 64A8 DDE1 pop ix 484: 64AA C9 ret 485: 64AB 3E20 body: ld a,32 ;"Illegal drive number" 486: 64AD C0 ret nz 487: 64AE 78 ld a,b ;The first test will return 488: 64AF A7 and a ; to the caller on @DCSTAT 489: 64B0 C8 ret z ; and set the Z-flag with A=0 490: 64B1 FE07 notdcs: cp 7 491: 64B3 2804 jr z,rslct ;Transfer on @RSLCT 492: 64B5 3004 jr nc,diskio ;Transfer on physical I/O request 493: ;*=*=* 494: ; @SLCT, @DCINIT, @DCRES, @RSTOR, @STEPI or @SEEK: no-op 495: ;*=*=* 496: 64B7 97 retzer: sub a 497: 64B8 C9 ret 498: ;*=*=* 499: ; The RSLCT function should return with the hardware 500: ; write protection status. Set bit 6 of the accumulator 501: ; to indicate the drive is write-protected 502: ;*=*=* 503: 64B9 97 rslct: sub a ;No emulated hardware WP for now 504: 64BA C9 ret 505: ;*=*=* 506: 64BB CB50 diskio: bit 2,b ;Test if read or write commands 507: 64BD 2058 jr nz,wrcmd ;Transfer if functions <12-15> 508: 64BF FE0A cp 10 509: 64C1 2847 jr z,vrsec 510: 64C3 304E jr nc,rdtrk 511: 64C5 FE09 cp 9 512: 64C7 2804 jr z,rdsec 513: 64C9 3E20 rdhdr: ld a,32 ;Not supported ("Illegal drive number") 514: 64CB A7 and a 515: 64CC C9 ret 516: ;*=*=* 517: 64CD rdsec: ;Read a sector of data 518: 64CD FD7E06 ld a,(iy+6) ;Get high cyl # 519: 64D0 BA cp d ;At or below it? 520: 64D1 3003 jr nc,rdok 521: 64D3 3E02 ld a,2 ;"Seek error during read" 522: 64D5 C9 ret ;NZ already set 523: 64D6 D5 rdok: push de 524: 64D7 E5 push hl 525: 64D8 CD6F65 call doseek ;Setup and do lseek 526: 64D9 rx01 equ $-2 527: 64DB E1 pop hl 528: 64DC 3E05 ld a,5 ;"Data record not found during read" 529: 64DE 2007 jr nz,rddun 530: 64E0 010001 ld bc,256 531: 64E3 ED32 defw emt_read 532: 64E5 3E04 ld a,4 ;"Parity error during read" 533: 64E7 D1 rddun: pop de 534: 64E8 C0 ret nz 535: 64E9 78 ld a,b ;Check for end of file 536: 64EA B1 or c 537: 64EB 2012 jr nz,rddun2 538: 64ED D5 push de 539: 64EE E5 push hl ;Return a block full of 0E5H 540: 64EF C5 push bc 541: 64F0 36E5 ld (hl),0e5h 542: 64F2 54 ld d,h 543: 64F3 5D ld e,l 544: 64F4 13 inc de 545: 64F5 01FF00 ld bc,0ffh 546: 64F8 EDB0 ldir 547: 64FA C1 pop bc 548: 64FB E1 pop hl 549: 64FC D1 pop de 550: 64FD 97 sub a 551: 64FE C9 ret 552: 64FF 7A rddun2: ld a,d 553: 6500 FD9609 sub (iy+9) 554: 6503 2003 jr nz,rddun1 555: 6505 C606 add a,6 ;"Attempted to read system data record" 556: 6507 C9 ret 557: 6508 97 rddun1: sub a 558: 6509 C9 ret 559: ;*=*=* 560: 650A vrsec: ;Read/verify -- we don't bother reading 561: 650A FD7E06 ld a,(iy+6) ;Get high cyl # 562: 650D BA cp d ;At or below it? 563: 650E 30EF jr nc,rddun2 ;Go if so 564: 6510 3E02 ld a,2 ;"Seek error during read" 565: 6512 C9 ret ;NZ already set 566: ;*=*=* 567: ; On RDSEC and VRSEC, if the read referenced the 568: ; directory cylinder and was successful, 569: ; then you need to return an error code 6. A floppy 570: ; disk controller will provide the indicated status. 571: ; Hard disk users may have to compare the requested 572: ; cylinder to DIRCYL in the DCT. 573: ;*=*=* 574: 6513 3E20 rdtrk: ld a,32 ;Not supported ("Illegal drive number") 575: 6515 A7 and a 576: 6516 C9 ret 577: ;*=*=* 578: 6517 FDCB037E wrcmd: bit 7,(iy+3) ;Check for software write protect 579: 651B 2803 jr z,wrcmd1 ;Transfer if no soft WP 580: 651D 3E0F ld a,15 ;Set "Write protected disk" error 581: 651F C9 ret 582: 6520 FE0E wrcmd1: cp 14 ;Now parse functions 12-15 583: 6522 2829 jr z,wrssc 584: 6524 3045 jr nc,wrtrk 585: 6526 FE0D cp 13 586: 6528 281E jr z,wrsec 587: ;*=*=* 588: 652A hdfmt: ;Low-level format (=erase) 589: 652A FD3609FF ld (iy+9),0ffh ;Invalidate directory cylinder 590: 652E D5 push de 591: 652F E5 push hl 592: 6530 DD5E00 ld e,(ix) ;Get fd 593: 6533 DD5601 ld d,(ix+1) 594: 6536 210001 exists: ld hl,256 ;Truncate file to just the header 595: 6539 229964 ld (offset+1),hl 596: 653A rx07 equ $-2 597: 653C 219864 ld hl,offset 598: 653D rx08 equ $-2 599: 653F ED3D defw emt_ftruncate 600: 6541 E1 creatd: pop hl 601: 6542 D1 pop de 602: 6543 3E0E ld a,14 ;"Write fault on disk drive" 603: 6545 C0 ret nz 604: 6546 97 sub a 605: 6547 C9 ret 606: ;*=*=* 607: 6548 wrsec: ;Write with X'FB' data address mark 608: 6548 7A ld a,d ;Check if writing track 0, sector 0 609: 6549 B3 or e 610: 654A CC1566 call z,setdir ;Set directory cyl in Reed header 611: 654B rx20 equ $-2 612: ;*=*=* 613: 654D wrssc: ;Write with X'F8' data address mark 614: 654D FD7E06 ld a,(iy+6) ;Get high cyl # 615: 6550 BA cp d ;Beyond it? 616: 6551 3003 jr nc,wrok1 617: 6553 3E0A ld a,10 ;"Seek error during write" 618: 6555 C9 ret ;NZ already set 619: ;*=*=* 620: 6556 D5 wrok1: push de 621: 6557 E5 push hl 622: 6558 CD6F65 call doseek 623: 6559 rx04 equ $-2 624: 655B E1 pop hl 625: 655C 3E0D ld a,13 ;"Data record not found during write" 626: 655E 2007 jr nz,wrdun 627: 6560 010001 ld bc,256 628: 6563 ED33 defw emt_write 629: 6565 3E0C ld a,12 ;"Parity error during write" 630: 6567 D1 wrdun: pop de 631: 6568 C0 ret nz 632: 6569 97 sub a 633: 656A C9 ret 634: ;*=*=* 635: 656B 3E20 wrtrk: ld a,32 ;Write track 636: 656D A7 and a ;Not supported ("Illegal drive number") 637: 656E C9 ret 638: ;*=*=* 639: ; Perform lseek before r/w 640: ;*=*=* 641: 656F 97 doseek: sub a ;sec/cyl to hl, xlate 0 to 256 642: 6570 67 ld h,a 643: 6571 FD8605 add a,(iy+5) 644: 6574 6F ld l,a 645: 6575 2001 jr nz,noinc 646: 6577 24 inc h 647: 6578 4A noinc: ld c,d ;cyl# to c 648: 6579 43 ld b,e ;sec# to b 649: 657A 79 ld a,c ;model I/III call uses a, not c 650: 657B 3E5B domul: ld a,@mul16 ;hla = hl * c, smash de 651: 657D EF rst 40 652: 657E 54 ld d,h ;sec# to de (h is 0) 653: 657F 58 ld e,b 654: 6580 65 ld h,l ;product to hl 655: 6581 6F ld l,a 656: 6582 23 inc hl ;add 1 extra for header 657: 6583 19 add hl,de 658: 6584 EB ex de,hl ;offset to de 659: 6585 219A64 ld hl,offset+2 660: 6586 rx15 equ $-2 661: 6588 72 ld (hl),d 662: 6589 2B dec hl 663: 658A 73 ld (hl),e 664: 658B 2B dec hl 665: 658C 010000 ld bc,0 666: 658F 71 ld (hl),c 667: 6590 DD5E00 ld e,(ix) ;Get fd 668: 6593 DD5601 ld d,(ix+1) 669: 6596 ED34 defw emt_lseek 670: 6598 C9 ret 671: 672: ;*=*=* 673: ; Open file and read geometry if needed, and 674: ; get address of correct fd to ix. 675: ;*=*=* 676: 6599 DD218864 ckopen: ld ix,fd ;Compute fd address 677: 659B rx02 equ $-2 678: 659D D5 push de 679: 659E 1600 ld d,0 680: 65A0 FD7E04 ld a,(iy+4) 681: 65A3 E60F and 0fh 682: 65A5 07 rlca 683: 65A6 5F ld e,a 684: 65A7 DD19 add ix,de 685: 65A9 D1 pop de 686: 65AA DD7E00 ld a,(ix) ;fd == -1? 687: 65AD DDA601 and (ix+1) 688: 65B0 3C inc a 689: 65B1 2802 jr z,doopen 690: 65B3 97 sub a 691: 65B4 C9 ret 692: 65B5 D5 doopen: push de 693: 65B6 C5 push bc 694: 65B7 E5 push hl 695: 65B8 010200 ld bc,EO_RDWR ;Prepare to open 696: 65BB 11B601 ld de,0666o ;mode 697: 65BE 214F66 ld hl,hard_ ;name 698: 65BF rx05 equ $-2 699: 65C1 FD7E04 ld a,(iy+4) 700: 65C4 E60F and 0fh 701: 65C6 C630 add a,'0' 702: 65C8 325566 ld (hadr),a 703: 65C9 rx09 equ $-2 704: 65CB ED3E defw emt_opendisk 705: 65CD DD7300 ld (ix),e 706: 65D0 DD7201 ld (ix+1),d 707: 65D3 203C jr nz,opnerr 708: 65D5 219864 ld hl,offset ;Prepare to read geometry 709: 65D6 rx13 equ $-2 710: 65D8 361C ld (hl),28 ;offset to cyl/sec/gran params 711: 65DA 010000 ld bc,0 712: 65DD ED439964 ld (offset+1),bc 713: 65DF rx14 equ $-2 714: 65E1 ED34 defw emt_lseek 715: 65E3 202C jr nz,opnerr 716: 65E5 010300 ld bc,3 ;length 717: 65E8 ED32 defw emt_read ;use offset buffer 718: 65EA 2025 jr nz,opnerr 719: 65EC 7E ld a,(hl) ;cyl 720: 65ED 3D dec a 721: 65EE FD7706 ld (iy+6),a ;max cylinder 722: 65F1 23 inc hl 723: 65F2 46 ld b,(hl) ;sec 724: 65F3 FD7005 ld (iy+5),b 725: 65F6 23 inc hl 726: 65F7 4E ld c,(hl) ;gran 727: 65F8 58 ld e,b ;compute sec/gran 728: 65F9 79 ld a,c ;model I/III call uses a, not c 729: 65FA 3E5D dodiv: ld a,@div8 ;a = e / c, e = e % c 730: 65FC EF rst 40 ;remainder mbz, but we don't check here 731: 65FD 3D dec a 732: 65FE 0D dec c 733: 65FF CB09 rrc c 734: 6601 CB09 rrc c 735: 6603 CB09 rrc c 736: 6605 B1 or c 737: 6606 FD7707 ld (iy+7),a ;heads, secs per track 738: 6609 FD7708 ld (iy+8),a ;grans, secs per gran 739: 660C FD3609FF ld (iy+9),0ffh ;dircyl unknown 740: 6610 97 sub a ;no error 741: 6611 E1 opnerr: pop hl 742: 6612 C1 pop bc 743: 6613 D1 pop de 744: 6614 C9 ret 745: ;*=*=* 746: ; Sleazy trick to update dir cyl in Reed header: do 747: ; it whenever track 0, sector 0 is written. 748: ; Only important if sharing images with Reed emulator. 749: ;*=*=* 750: 6615 E5 setdir: push hl 751: 6616 C5 push bc 752: 6617 D5 push de 753: 6618 219864 ld hl,offset 754: 6619 rx18 equ $-2 755: 661B 42 ld b,d ;de is known to be 0 here 756: 661C 4B ld c,e 757: 661D DD5E00 ld e,(ix) ;Get fd 758: 6620 DD5601 ld d,(ix+1) 759: 6623 361F ld (hl),31 ;offset to dir cyl param 760: 6625 ED439964 ld (offset+1),bc 761: 6627 rx19 equ $-2 762: 6629 ED34 defw emt_lseek 763: 662B FD7E09 ld a,(iy+9) ;dir cyl value to write 764: 662E 77 ld (hl),a 765: 662F 03 inc bc 766: 6630 ED33 defw emt_write 767: 6632 D1 pop de ;cheat, ignore errors 768: 6633 C1 pop bc 769: 6634 E1 pop hl 770: 6635 C9 ret 771: ;*=*=* 772: ; Boot-time initialization 773: ;*=*=* 774: 6636 11FFFF dvrcfg: ld de,-1 ;@ICNFG chains in here 775: 6639 ED3F defw emt_closedisk ;close any files left from before reboot 776: 663B CD4166 call dvrini 777: 663C rx11 equ $-2 778: 663E 54696D link: defb 'Tim' ;Replaced by next link in @ICNFG chain 779: 6641 218864 dvrini: ld hl,fd 780: 6642 rx12 equ $-2 781: 6644 54 ld d,h 782: 6645 5D ld e,l 783: 6646 13 inc de 784: 6647 36FF ld (hl),0ffh 785: 6649 010F00 ld bc,ndrive*2-1 786: 664C EDB0 ldir 787: 664E C9 ret 788: ;*=*=* 789: ; Disk name: hardM-N for model M (1,3,4), number N (0-7) 790: ;*=*=* 791: 664F 68617264 hard_: defb 'hard' 792: 6653 312D hmod: defb '1-' 793: 6655 3000 hadr: defb '0',0 794: 795: 6656 dvrend equ $-1 796: 01E0 length equ $-entry 797: 6657 7964D964 reltab: defw rx00,rx01,rx02,rx03,rx04,rx05,rx06,rx07,rx08,rx09 9B65A364 5965BF65 A6643A65 3D65C965 798: 666B D5613C66 defw rx10,rx11,rx12,rx13,rx14,rx15,rx16,rx17,rx18,rx19 4266D665 DF658665 98602961 19662766 799: 667F 4B650000 defw rx20,0 800: 6000 end instal Statistics: 146 symbols 1393 bytes Symbol Table: @div8 = 5d emt_write =33ed rdok 64d6 @divea1 =4b7b entry 6477 rdsec 64cd @divea3 =4b7a eo_append = 400+ rdtrk 6513 @dsply = a eo_creat = 40+ relo 6249 @dsply1 =4467 eo_excl = 80+ reltab 6657 @dsply3 =4467 eo_rdonly = 0+ retzer 64b7+ @flags = 65 eo_rdwr = 2 rloop 6258 @gtdcb = 52 eo_trunc = 200+ rslct 64b9 @gtmod = 53 eo_wronly = 1+ rx00 =6479 @high = 64 errbuf 6377 rx01 =64d9 @icnfg1 =4303 etx = 3 rx02 =659b @icnfg3 =421d exists 6536+ rx03 =64a3 @keyin = 9 fd 6488 rx04 =6559 @keyin1 = 40 hadr 6655 rx05 =65bf @keyin3 = 40 hard_ 664f rx06 =64a6 @logot = c hdfmt 652a+ rx07 =653a @logot1 =447b hello_ 629d rx08 =653d @logot3 =428a high1 =4049 rx09 =65c9 @mul16 = 5b high3 =4411 rx10 =61d5 @mult1 =4b8f hitbrk 623f rx11 =663c @mult3 =444e hitbrk_ 6366 rx12 =6642 asku1 604d hmod 6653 rx13 =65d6 asku3 60de instal 6000 rx14 =65df asku4 6155 lcptr 636f+ rx15 =6586 begin 64a0 length = 1e0 rx16 =6098 body 64ab lf = a+ rx17 =6129 cflag1 =4758 link 663e rx18 =6619 cflag3 =4758 logot 6242 rx19 =6627 ckopen 6599 lsdos6 6136 rx20 =654b cr = d m3flag = 125 setdct 61ef creatd 6541+ model3 60a5 setdir 6615 curdl 622f modnam 647c uerror 6226+ curdl_ 62d5 modptr 6484 unit 6375 dct 6373 move 61e1 unit_ 634a diskio 64bb ndrive = 8 usehi 61a6 dodiv 65fa needdr 6233 viaset 6237 domul 657b needdr_ 6330 viaset_ 6306 doopen 65b5 newend 6371 vrsec 650a dorelo 61bc nextmd 6294 wrcmd 6517 doseek 656f noinc 6578 wrcmd1 6520 dvrcfg 6636 nomem 623b wrdun 6567 dvrend =6656 nomem_ 62e8 wrok1 6556 dvrini 6641 notdcs 64b1+ wrsec 6548 emt_closedisk =3fed offset 6498 wrssc 654d emt_ftruncate =3ded opnerr 6611 wrtrk 656b emt_lseek =34ed rddun 64e7 xgtm1 6277 emt_opendisk =3eed rddun1 6508 xgtm2 628a emt_read =32ed rddun2 64ff xgtmod 6270 emt_strerror =35ed rdhdr 64c9+