1: ;; import.z 2: ;; Timothy Mann, 8/24/97 3: ;; $Date: 2006/05/15 00:49:19 $ 4: ;; 5: ;; Copyright (c) 1997, 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: ;; Use xtrs emulator traps to copy a file from Unix to TRS-80 14: ;; Usage: IMPORT [-lne] unixfile [tofile] 15: ;; Parameter -l will convert the Unix file to lower case. 16: ;; (Needed for NEWDOS/80. They insist on uppercasing the 17: ;; command line.) 18: ;; If the -n parameter is given, each newline ('\n') in the Unix 19: ;; file is converted to a carriage return ('\r'), the TRS-80 end of 20: ;; line character. 21: ;; The program tries to determine what DOS it is running on and use 22: ;; the correct FCB end of file convention, but this works only on 23: ;; TRSDOS, LDOS, and NEWDOS/80. For other DOSes that use the 24: ;; NEWDOS/80 convention (such as DOSPLUS), give the -e paramter. 25: ;; If the tofile parameter is omitted, the last component of the 26: ;; Unix pathname is used, with '.' changed to '/'. If this is 27: ;; not a legal TRS-80 filename, you get an error message. 28: 29: ;; Model I/III addresses 30: 441C @fspec equ 441ch 31: 4420 @init equ 4420h 32: 4424 @open equ 4424h 33: 4428 @close equ 4428h 34: 4436 @read equ 4436h 35: 4439 @write equ 4439h 36: 4409 @error equ 4409h 37: 402D @exit equ 402dh 38: 4030 @abort equ 4030h 39: 001B @put equ 001bh 40: 401D dodcb$ equ 401dh 41: 42: ;; Model 4 SVCs 43: 0028 @svc equ 40 ; rst address for SVCs 44: ;@svc equ 5 ; older zmac requires 8080-style "rst 5" 45: 004E @fspec6 equ 78 46: 003A @init6 equ 58 47: 003B @open6 equ 59 48: 003C @close6 equ 60 49: 0043 @read6 equ 67 50: 004B @write6 equ 75 51: 001A @error6 equ 26 52: 0016 @exit6 equ 22 53: 0015 @abort6 equ 21 54: 000A @dsply6 equ 10 55: 56: ;; Model 4 only: file init or open with wrong LRL. Can be ignored. 57: 002A lrlerr equ 42 58: 59: 5200 org 5200h 60: 61: ;; Jump tables for OS independence 62: 5200 startj: 63: 5200 CD1C44 fspec: call @fspec 64: 5203 C9 ret 65: 5204 CD2044 init: call @init 66: 5207 C9 ret 67: 5208 CD2444 open: call @open 68: 520B C9 ret 69: 520C CD2844 close: call @close 70: 520F C9 ret 71: 5210 CD3644 reed: call @read 72: 5213 C9 ret 73: 5214 CD3944 write: call @write 74: 5217 C9 ret 75: 5218 CD0944 error: call @error 76: 521B C9 ret 77: 521C CD2D40 exit: call @exit 78: 521F C9 ret 79: 5220 CD3040 abort: call @abort 80: 5223 C9 ret 81: 5224 CDA953 dsply: call dsply5 82: 5227 C9 ret 83: 5228 CDDB53 setern: call setern5 84: 522B C9 ret 85: 522C endj: 86: 87: ; Model 4 88: 522C startj6: 89: 522C 3E4E ld a, @fspec6 90: 522E EF rst @svc 91: 522F C9 ret 92: 5230 3E3A ld a, @init6 93: 5232 EF rst @svc 94: 5233 C9 ret 95: 5234 3E3B ld a, @open6 96: 5236 EF rst @svc 97: 5237 C9 ret 98: 5238 3E3C ld a, @close6 99: 523A EF rst @svc 100: 523B C9 ret 101: 523C 3E43 ld a, @read6 102: 523E EF rst @svc 103: 523F C9 ret 104: 5240 3E4B ld a, @write6 105: 5242 EF rst @svc 106: 5243 C9 ret 107: 5244 3E1A ld a, @error6 108: 5246 EF rst @svc 109: 5247 C9 ret 110: 5248 3E16 ld a, @exit6 111: 524A EF rst @svc 112: 524B C9 ret 113: 524C 3E15 ld a, @abort6 114: 524E EF rst @svc 115: 524F C9 ret 116: 5250 3E0A ld a, @dsply6 117: 5252 EF rst @svc 118: 5253 C9 ret 119: 5254 CDEC53 call setern6 120: 5257 C9 ret 121: 122: ; Nonzero for LDOS ern convention 123: 5258 01 ernldos: db 1 124: 125: ; Emulator trap instructions, byte-reversed for use in defw: 126: 30ED emt_open equ 30edh 127: 31ED emt_close equ 31edh 128: 32ED emt_read equ 32edh 129: 33ED emt_write equ 33edh 130: 34ED emt_lseek equ 34edh 131: 35ED emt_strerror equ 35edh 132: 133: 0003 EO_ACCMODE equ 3q 134: 0000 EO_RDONLY equ 0q 135: 0001 EO_WRONLY equ 1q 136: 0002 EO_RDWR equ 2q 137: 0040 EO_CREAT equ 100q 138: 0080 EO_EXCL equ 200q 139: 0200 EO_TRUNC equ 1000q 140: 0400 EO_APPEND equ 2000q 141: 142: 2000 iobsize equ 8192 ; must be divisible by 256 143: 144: 5259 import: 145: 5259 3A0A00 ld a, (000ah) ; Model 4? 146: 525C FE40 cp 40h 147: 525E 280D jr z, not4 148: 5260 E5 push hl 149: 5261 110052 ld de, startj 150: 5264 212C52 ld hl, startj6 151: 5267 012C00 ld bc, endj - startj 152: 526A EDB0 ldir 153: 526C E1 pop hl 154: 526D not4: 155: 526D 3A2744 ld a, (4427h) ; system id for Newdos/80... 156: 5270 D682 sub 82h ; ...should be 82h (v2.0) 157: 5272 2805 jr z, gotid 158: 5274 3A1F44 ld a, (441fh) ; system version number for most other DOSes 159: 5277 D613 sub 13h ; TRSDOS 1.3? 160: 5279 325852 gotid: ld (ernldos), a 161: 162: 527C 7E flag0: ld a, (hl) ; look for flags 163: 527D FE20 cp ' ' 164: 527F DA1453 jp c, usage ; error if line ends here 165: 5282 2003 jr nz, flag1 166: 5284 23 inc hl 167: 5285 18F5 jr flag0 168: 5287 FE2D flag1: cp '-' 169: 5289 202B jr nz, unix1 170: 528B 23 inc hl 171: 528C 7E ld a, (hl) 172: 528D F620 flag3: or 20h 173: 528F FE65 cp 'e' 174: 5291 2006 jr nz, flagl 175: 5293 97 sub a 176: 5294 325852 ld (ernldos), a 177: 5297 1814 jr flag2 178: 5299 FE6C flagl: cp 'l' 179: 529B 2007 jr nz, flagn ; check for next flag 180: 529D 3E01 ld a, 1 181: 529F 32F353 ld (lflag), a 182: 52A2 1809 jr flag2 183: 52A4 FE6E flagn: cp 'n' 184: 52A6 206C jr nz, usage ; unknown flag 185: 52A8 3E01 ld a, 1 186: 52AA 32F453 ld (nflag), a 187: 52AD 23 flag2: inc hl 188: 52AE 7E ld a, (hl) 189: 52AF FE20 cp ' ' 190: 52B1 20DA jr nz, flag3 ; another flag follows 191: 52B3 23 inc hl 192: 52B4 18C6 jr flag0 193: 194: 52B6 118C54 unix1: ld de, iobuf ; copy Unix filename 195: 52B9 3E20 ld a, ' ' 196: 52BB BE unix2: cp (hl) 197: 52BC EDA0 ldi 198: 52BE 38FB jr c, unix2 199: 52C0 1B dec de ; NUL terminate Unix name 200: 52C1 3E00 ld a, 0 201: 52C3 12 ld (de), a 202: 52C4 2812 jr z, trs80 ; go if two names given 203: 204: ;; Translate last component of Unix name to TRS-80 name 205: 52C6 2B dec hl ; back up to terminator 206: 52C7 2B unix3: dec hl ; back up to last byte of name 207: 52C8 7E ld a, (hl) 208: 52C9 FE2E cp '.' ; change '.' to '/' 209: 52CB 2002 jr nz, notdot 210: 52CD 362F ld (hl), '/' 211: 52CF FE2F notdot: cp '/' 212: 52D1 2804 jr z, unix4 213: 52D3 FE20 cp ' ' 214: 52D5 20F0 jr nz, unix3 215: 52D7 23 unix4: inc hl ; point to start of modified last component 216: 217: 52D8 115C54 trs80: ld de, dcb ; ready to get TRS-80 filename from (HL) 218: 52DB CD0052 call fspec 219: 52DE 2034 jr nz, usage 220: 52E0 218C54 ld hl, iobuf ; Unix path 221: 52E3 3AF353 ld a, (lflag) 222: 52E6 B7 or a 223: 52E7 C4BE53 call nz, lcconv ; convert path to lower case 224: 52EA 010000 ld bc, EO_RDONLY 225: 52ED 110000 ld de, 0 ; mode (ignored) 226: 52F0 ED30 defw emt_open 227: 52F2 2806 jr z, openok ; go if OK 228: 52F4 211C54 ld hl, uopner ; error message and exit 229: 52F7 C39653 jp uerror 230: 231: 52FA D5 openok: push de ; save fd 232: 52FB 218C54 ld hl, iobuf 233: 52FE 115C54 ld de, dcb 234: 5301 0600 ld b, 0 235: 5303 CD0452 call init ; open the file 236: 5306 D1 pop de 237: 5307 2814 jr z, opn2ok 238: 5309 FE2A cp lrlerr 239: 530B 2810 jr z, opn2ok 240: 530D 4F ld c, a 241: 530E CD1852 call error 242: 5311 C32052 jp abort 243: 5314 21F553 usage: ld hl, usager ; error message and exit 244: 5317 CD2452 call dsply 245: 531A C32052 jp abort 246: 247: ;; Read 248: 531D rloop: 249: 531D 218C54 opn2ok: ld hl, iobuf ; read a buffer 250: 5320 010020 ld bc, iobsize 251: 5323 ED32 defw emt_read 252: 5325 2805 jr z, readok 253: 5327 213154 ld hl, urder ; read error (!!code in A) 254: 532A 186A jr uerror 255: 532C D5 readok: push de ; save fd 256: 257: ;; Translate 258: 532D 3AF453 ld a, (nflag) ; check for NL feature 259: 5330 A7 and a 260: 5331 2817 jr z, nlfals 261: 5333 218C54 ld hl, iobuf 262: 5336 C5 push bc ; save byte count 263: 5337 3E0A ld a, 0ah 264: 5339 160D ld d, 0dh 265: 533B 0C inc c ; deal with b=0 and/ c=0 266: 533C 04 inc b 267: 533D 1805 jr tstrt 268: 533F BE tloop: cp (hl) 269: 5340 2001 jr nz, notcr 270: 5342 72 ld (hl), d 271: 5343 23 notcr: inc hl 272: 5344 0D tstrt: dec c 273: 5345 20F8 jr nz, tloop 274: 5347 10F6 djnz tloop 275: 5349 C1 pop bc ; restore byte count 276: 277: ;; Write 278: 534A C5 nlfals: push bc ; save byte count 279: 534B 218C54 ld hl, iobuf 280: 534E 115C54 ld de, dcb 281: 5351 04 inc b ; deal with b=0 and/or c=0 282: 5352 79 ld a, c 283: 5353 A7 and a 284: 5354 2810 jr z, wstrt 285: 5356 225F54 wloop: ld (dcb+3), hl 286: 5359 CD1452 call write ; write 256 bytes to file 287: 535C 2807 jr z, wrok 288: 535E 4F ld c, a 289: 535F CD1852 call error ; oops, i/o error 290: 5362 C32052 jp abort 291: 5365 24 wrok: inc h 292: 5366 10EE wstrt: djnz wloop 293: 5368 C1 pop bc ; restore byte count 294: 295: ;; Done? 296: 5369 D1 pop de ; restore fd 297: 536A 79 ld a, c 298: 536B A7 and a 299: 536C 2003 jr nz, closit ; done for sure 300: 536E B8 cp b 301: 536F 20AC jr nz, rloop ; maybe not done (sloppy) 302: 303: 5371 ED31 closit: defw emt_close ; close Unix file 304: 5373 2805 jr z, closok 305: 5375 214654 ld hl, uclser ; close error (!!code in A) 306: 5378 181C jr uerror 307: 537A 79 closok: ld a, c 308: 537B 326454 ld (dcb+8), a ; set EOF offset 309: 537E CD2852 call setern ; set ERN (in case shortening file) 310: 5381 115C54 ld de, dcb 311: 5384 CD0C52 call close ; close the TRS-80 file 312: 5387 2807 jr z, cls2ok 313: 5389 4F ld c, a 314: 538A CD1852 call error ; oops, i/o error 315: 538D C32052 jp abort 316: 5390 210000 cls2ok: ld hl, 0 ; all is well 317: 5393 C31C52 jp exit 318: 319: ;; Unix error, msg in hl, errno in a 320: 5396 F5 uerror: push af 321: 5397 CD2452 call dsply 322: 539A F1 pop af 323: 539B 218C54 ld hl, iobuf 324: 539E 010001 ld bc, 256 325: 53A1 ED35 defw emt_strerror 326: 53A3 CD2452 call dsply 327: 53A6 C32052 jp abort 328: 329: ;; Display message in HL. 03h terminate, 0dh newline and terminate. 330: 53A9 111D40 dsply5: ld de, dodcb$ 331: 53AC E5 push hl 332: 53AD 7E dsply0: ld a, (hl) 333: 53AE FE03 cp 03h 334: 53B0 280A jr z, dsply1 335: 53B2 F5 push af 336: 53B3 CD1B00 call @put 337: 53B6 F1 pop af 338: 53B7 23 inc hl 339: 53B8 FE0D cp 0dh 340: 53BA 20F1 jr nz, dsply0 341: 53BC E1 dsply1: pop hl 342: 53BD C9 ret 343: 344: ;; Convert (NUL terminated) string in HL to lower case. 345: 53BE E5 lcconv: push hl 346: 53BF 54 ld d, h 347: 53C0 5D ld e, l 348: 53C1 7E lcloop: ld a, (hl) 349: 53C2 FE5B cp 5bh ; use '[' or uparrow as escape 350: 53C4 2004 jr nz, lconv1 351: 53C6 23 inc hl 352: 53C7 7E ld a, (hl) 353: 53C8 1809 jr lconv2 ; char after esc: don't convert 354: 53CA D641 lconv1: sub 'A' 355: 53CC FE1A cp 26 356: 53CE 7E ld a, (hl) 357: 53CF 3002 jr nc, lconv2 358: 53D1 F620 or 20h ; convert to lower case 359: 53D3 12 lconv2: ld (de), a 360: 53D4 23 inc hl 361: 53D5 13 inc de 362: 53D6 B7 or a ; NUL terminator? 363: 53D7 20E8 jr nz, lcloop 364: 53D9 E1 pop hl 365: 53DA C9 ret 366: 367: ;; EOF handling differs between TRS-80 DOSes: 368: ;; For TRSDOS 2.3 and LDOS, word (dcb+12) contains the number of 369: ;; 256 byte records in the file, byte (dcb+8) contains the EOF 370: ;; offset in the last record (0=256). 371: ;; For NEWDOS/80 and TRSDOS 1.3, byte (dcb+8) and word (dcb+12) 372: ;; form a 24 bit number containing the relative byte address of EOF. 373: ;; Thus (dcb+12) differs by one if the file length is not a 374: ;; multiple of 256 bytes. DOSPLUS also uses this convention, 375: ;; and NEWDOS 2.1 probably does too (not checked). 376: 377: ; Set ending record number of file to current position 378: ; EOF offset in C; destroys A, HL 379: 53DB setern5: 380: 53DB 2A6654 ld hl, (dcb+10) ; current record number 381: 53DE 3A5852 ld a, (ernldos) ; get ERN convention 382: 53E1 B7 or a 383: 53E2 2004 jr nz, noadj ; go if TRSDOS 2.3/LDOS convention 384: 53E4 B1 adj: or c ; length multiple of 256 bytes? 385: 53E5 2801 jr z, noadj ; go if so 386: 53E7 2B dec hl ; no, # of records - 1 387: 53E8 226854 noadj: ld (dcb+12), hl 388: 53EB C9 ret 389: 390: ; All Model 4 mode operating systems should be TRSDOS/LS-DOS 6.x compatible 391: 53EC setern6: 392: 53EC 2A6654 ld hl, (dcb+10) 393: 53EF 226854 ld (dcb+12), hl 394: 53F2 C9 ret 395: 396: 53F3 00 lflag: defb 0 397: 53F4 00 nflag: defb 0 398: 399: 53F5 55736167 usager: defb 'Usage: IMPORT [-lne] unixfile [tofile]', 0dh 653A2049 4D504F52 54205B2D 6C6E655D 20756E69 7866696C 65205B74 6F66696C 655D0D 400: 541C 4572726F uopner: defb 'Error in Unix open: ', 03h 7220696E 20556E69 78206F70 656E3A20 03 401: 5431 4572726F urder: defb 'Error in Unix read: ', 03h 7220696E 20556E69 78207265 61643A20 03 402: 5446 4572726F uclser: defb 'Error in Unix close: ', 03h 7220696E 20556E69 7820636C 6F73653A 2003 403: 404: 545C dcb: defs 48 ; 48 for Model III TRSDOS 1.3 405: 548C iobuf: defs iobsize 406: 407: 5259 end import Statistics: 103 symbols 604 bytes Symbol Table: @abort =4030 emt_open =30ed nlfals 534a @abort6 = 15 emt_read =32ed noadj 53e8 @close =4428 emt_strerror =35ed not4 526d @close6 = 3c emt_write =33ed+ notcr 5343 @dsply6 = a endj 522c notdot 52cf @error =4409 eo_accmode = 3+ open 5208+ @error6 = 1a eo_append = 400+ openok 52fa @exit =402d eo_creat = 40+ opn2ok 531d @exit6 = 16 eo_excl = 80+ readok 532c @fspec =441c eo_rdonly = 0 reed 5210+ @fspec6 = 4e eo_rdwr = 2+ rloop 531d @init =4420 eo_trunc = 200+ setern 5228 @init6 = 3a eo_wronly = 1+ setern5 53db @open =4424 ernldos 5258 setern6 53ec @open6 = 3b error 5218 startj 5200 @put = 1b exit 521c startj6 522c @read =4436 flag0 527c tloop 533f @read6 = 43 flag1 5287 trs80 52d8 @svc = 28 flag2 52ad tstrt 5344 @write =4439 flag3 528d uclser 5446 @write6 = 4b flagl 5299 uerror 5396 abort 5220 flagn 52a4 unix1 52b6 adj 53e4+ fspec 5200 unix2 52bb close 520c gotid 5279 unix3 52c7 closit 5371 import 5259 unix4 52d7 closok 537a init 5204 uopner 541c cls2ok 5390 iobsize =2000 urder 5431 dcb 545c iobuf 548c usage 5314 dodcb =401d lcconv 53be usager 53f5 dsply 5224 lcloop 53c1 wloop 5356 dsply0 53ad lconv1 53ca write 5214 dsply1 53bc lconv2 53d3 wrok 5365 dsply5 53a9 lflag 53f3 wstrt 5366 emt_close =31ed lrlerr = 2a emt_lseek =34ed+ nflag 53f4