1: ;; export.z 2: ;; Timothy Mann, 8/24/97 3: ;; $Date: 2006/05/15 00:48:57 $ 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 TRS-80 to Unix 14: ;; Usage: EXPORT [-lne] fromfile [unixfile] 15: ;; Parameter -l will convert the Unix file to lower case. 16: ;; (Needed for NEWDOS/80. They insist on uppercasing the command line.) 17: ;; If the -n parameter is given, each carriage return ('\r') 18: ;; in the TRS-80 file is converted to a newline ('\n') in the Unix file. 19: ;; The program tries to determine what DOS it is running on and use 20: ;; the correct FCB end of file convention, but this works only on 21: ;; TRSDOS, LDOS, and NEWDOS/80. For other DOSes that use the 22: ;; NEWDOS/80 convention (such as DOSPLUS), give the -e paramter. 23: ;; If the unixfile parameter is omitted, the fromfile parameter is used, 24: ;; with '/' changed to '.'. 25: 26: ;; Model I/III addresses 27: 441C @fspec equ 441ch 28: 4420 @init equ 4420h 29: 4424 @open equ 4424h 30: 4428 @close equ 4428h 31: 4436 @read equ 4436h 32: 4439 @write equ 4439h 33: 4409 @error equ 4409h 34: 402D @exit equ 402dh 35: 4030 @abort equ 4030h 36: 001B @put equ 001bh 37: 401D dodcb$ equ 401dh 38: 39: ;; Model 4 SVCs 40: 0028 @svc equ 40 ; rst address for SVCs 41: ;@svc equ 5 ; older zmac requires 8080-style "rst 5" 42: 004E @fspec6 equ 78 43: 003A @init6 equ 58 44: 003B @open6 equ 59 45: 003C @close6 equ 60 46: 0043 @read6 equ 67 47: 004B @write6 equ 75 48: 001A @error6 equ 26 49: 0016 @exit6 equ 22 50: 0015 @abort6 equ 21 51: 000A @dsply6 equ 10 52: 53: ;; Model 4 only: file init or open with wrong LRL. Can be ignored. 54: 002A lrlerr equ 42 55: 56: 5200 org 5200h 57: 58: ;; Jump tables for OS independence 59: 5200 startj: 60: 5200 CD1C44 fspec: call @fspec 61: 5203 C9 ret 62: 5204 CD2044 init: call @init 63: 5207 C9 ret 64: 5208 CD2444 open: call @open 65: 520B C9 ret 66: 520C CD2844 close: call @close 67: 520F C9 ret 68: 5210 CD3644 reed: call @read 69: 5213 C9 ret 70: 5214 CD3944 write: call @write 71: 5217 C9 ret 72: 5218 CD0944 error: call @error 73: 521B C9 ret 74: 521C CD2D40 exit: call @exit 75: 521F C9 ret 76: 5220 CD3040 abort: call @abort 77: 5223 C9 ret 78: 5224 CDB553 dsply: call dsply5 79: 5227 C9 ret 80: 5228 CDE753 getern: call getern5 81: 522B C9 ret 82: 522C endj: 83: 84: ; Model 4 85: 522C startj6: 86: 522C 3E4E ld a, @fspec6 87: 522E EF rst @svc 88: 522F C9 ret 89: 5230 3E3A ld a, @init6 90: 5232 EF rst @svc 91: 5233 C9 ret 92: 5234 3E3B ld a, @open6 93: 5236 EF rst @svc 94: 5237 C9 ret 95: 5238 3E3C ld a, @close6 96: 523A EF rst @svc 97: 523B C9 ret 98: 523C 3E43 ld a, @read6 99: 523E EF rst @svc 100: 523F C9 ret 101: 5240 3E4B ld a, @write6 102: 5242 EF rst @svc 103: 5243 C9 ret 104: 5244 3E1A ld a, @error6 105: 5246 EF rst @svc 106: 5247 C9 ret 107: 5248 3E16 ld a, @exit6 108: 524A EF rst @svc 109: 524B C9 ret 110: 524C 3E15 ld a, @abort6 111: 524E EF rst @svc 112: 524F C9 ret 113: 5250 3E0A ld a, @dsply6 114: 5252 EF rst @svc 115: 5253 C9 ret 116: 5254 CDF753 call getern6 117: 5257 C9 ret 118: 119: ; Nonzero for LDOS ern convention 120: 5258 01 ernldos: db 1 121: 122: ; Emulator trap instructions, byte-reversed for use in defw: 123: 30ED emt_open equ 30edh 124: 31ED emt_close equ 31edh 125: 32ED emt_read equ 32edh 126: 33ED emt_write equ 33edh 127: 34ED emt_lseek equ 34edh 128: 35ED emt_strerror equ 35edh 129: 130: 0003 EO_ACCMODE equ 3q 131: 0000 EO_RDONLY equ 0q 132: 0001 EO_WRONLY equ 1q 133: 0002 EO_RDWR equ 2q 134: 0040 EO_CREAT equ 100q 135: 0080 EO_EXCL equ 200q 136: 0200 EO_TRUNC equ 1000q 137: 0400 EO_APPEND equ 2000q 138: 139: 5259 export: 140: 5259 3A0A00 ld a, (000ah) ; Model 4? 141: 525C FE40 cp 40h 142: 525E 280D jr z, not4 143: 5260 E5 push hl 144: 5261 110052 ld de, startj 145: 5264 212C52 ld hl, startj6 146: 5267 012C00 ld bc, endj - startj 147: 526A EDB0 ldir 148: 526C E1 pop hl 149: 526D not4: 150: 526D 3A2744 ld a, (4427h) ; system id for Newdos/80... 151: 5270 D682 sub 82h ; ...should be 82h (v2.0) 152: 5272 2805 jr z, gotid 153: 5274 3A1F44 ld a, (441fh) ; system version number for most other DOSes 154: 5277 D613 sub 13h ; TRSDOS 1.3? 155: 5279 325852 gotid: ld (ernldos), a 156: 157: 527C 7E flag0: ld a, (hl) ; look for flags 158: 527D FE20 cp ' ' 159: 527F DA9953 jp c, usage ; error if line ends here 160: 5282 2003 jr nz, flag1 161: 5284 23 inc hl 162: 5285 18F5 jr flag0 163: 5287 FE2D flag1: cp '-' 164: 5289 202C jr nz, fromf 165: 528B 23 inc hl 166: 528C 7E ld a, (hl) 167: 528D F620 flag3: or 20h 168: 528F FE65 cp 'e' 169: 5291 2006 jr nz, flagl 170: 5293 97 sub a 171: 5294 325852 ld (ernldos), a 172: 5297 1815 jr flag2 173: 5299 FE6C flagl: cp 'l' 174: 529B 2007 jr nz, flagn ; check for next flag 175: 529D 3E01 ld a, 1 176: 529F 32FC53 ld (lflag), a 177: 52A2 180A jr flag2 178: 52A4 FE6E flagn: cp 'n' 179: 52A6 C29953 jp nz, usage ; unknown flag 180: 52A9 3E01 ld a, 1 181: 52AB 32FD53 ld (nflag), a 182: 52AE 23 flag2: inc hl 183: 52AF 7E ld a, (hl) 184: 52B0 FE20 cp ' ' 185: 52B2 20D9 jr nz, flag3 ; another flag follows 186: 52B4 23 inc hl 187: 52B5 18C5 jr flag0 188: 189: 52B7 116A54 fromf: ld de, dcb ; ready to get LDOS filename from (HL) 190: 52BA 22FE53 ld (lfname), hl ; save if needed to default Unix name 191: 52BD CD0052 call fspec 192: 52C0 C29953 jp nz, usage 193: 194: 52C3 7E unix0: ld a, (hl) ; scan over Unix filename 195: 52C4 FE20 cp ' ' ; first skip spaces 196: 52C6 3814 jr c, usetrs ; if no Unix name, use translated TRS name 197: 52C8 2003 jr nz, unix1 198: 52CA 23 inc hl 199: 52CB 18F6 jr unix0 200: 52CD 119A54 unix1: ld de, iobuf ; copy Unix filename 201: 52D0 3E20 ld a, ' ' 202: 52D2 BE unix2: cp (hl) 203: 52D3 EDA0 ldi 204: 52D5 38FB jr c, unix2 205: 52D7 1B dec de 206: 52D8 97 sub a 207: 52D9 12 ld (de), a ; NUL terminate Unix name 208: 52DA 181C jr gotu 209: 210: 52DC 2AFE53 usetrs: ld hl, (lfname) ; translate TRS-80 name to Unix 211: 52DF 119A54 ld de, iobuf 212: 52E2 7E ut1: ld a, (hl) 213: 52E3 FE3A cp ':' ; drivespec? 214: 52E5 280F jr z, utdone ; done if so 215: 52E7 FE21 cp ' '+1 ; end of line? 216: 52E9 380B jr c, utdone ; done if so 217: 52EB FE2F cp '/' ; change '/' to '.' for extension 218: 52ED 2002 jr nz, notsl 219: 52EF 3E2E ld a, '.' 220: 52F1 12 notsl: ld (de), a 221: 52F2 23 inc hl 222: 52F3 13 inc de 223: 52F4 18EC jr ut1 224: 52F6 97 utdone: sub a ; NUL-terminate Unix name 225: 52F7 12 ld (de), a 226: 227: 52F8 219A54 gotu: ld hl, iobuf 228: 52FB 116A54 ld de, dcb 229: 52FE 0600 ld b, 0 230: 5300 CD0852 call open ; open the TRS-80 file 231: 5303 E1 pop hl 232: 5304 280B jr z, uname 233: 5306 FE2A cp lrlerr 234: 5308 2807 jr z, uname 235: 530A 4F ld c, a 236: 530B CD1852 call error 237: 530E C32052 jp abort 238: 239: 5311 219A54 uname: ld hl, iobuf ; path 240: 5314 3AFC53 ld a, (lflag) 241: 5317 B7 or a 242: 5318 C4CA53 call nz, lcconv ; convert filename to lower case 243: 531B 014102 ld bc, EO_WRONLY|EO_CREAT|EO_TRUNC 244: 531E 11B601 ld de, 0666q ; mode 245: 5321 ED30 defw emt_open ; open the Unix file 246: 5323 2806 jr z, opn2ok ; go if OK 247: 5325 212954 ld hl, uopner ; error message and exit 248: 5328 C3A253 jp uerror 249: 250: ;; Read 251: 532B CD2852 opn2ok: call getern ; count down records in bc 252: 253: 532E D5 loop: push de ; save fd 254: 532F 116A54 ld de, dcb 255: 5332 CD1052 call reed ; read 256 bytes from file 256: 5335 D1 pop de 257: 5336 280B jr z, rdok ; got a full 256 bytes 258: 5338 FE1C cp 28 ; eof? 259: 533A 283F jr z, closit ; yes, OK 260: 533C 4F ld c, a 261: 533D CD1852 call error ; oops, i/o error 262: 5340 C32052 jp abort 263: 5343 0B rdok: dec bc 264: 265: ;; Translate 266: 5344 C5 push bc ; save record count 267: 5345 3AFD53 ld a, (nflag) ; check for NL feature 268: 5348 A7 and a 269: 5349 280F jr z, nlfals 270: 534B 219A54 ld hl, iobuf 271: 534E 3E0D ld a, 0dh 272: 5350 010A00 ld bc, 000ah ; b := 0, c := 0ah 273: 5353 BE tloop: cp (hl) 274: 5354 2001 jr nz, notlf 275: 5356 71 ld (hl), c 276: 5357 23 notlf: inc hl 277: 5358 10F9 djnz tloop 278: 535A C1 nlfals: pop bc ; restore record count 279: 280: ;; Write 281: 535B 79 ld a, c 282: 535C B0 or b ; last record? 283: 535D C5 push bc ; save record count 284: 535E 010001 ld bc, 0100h ; byte count 285: 5361 2007 jr nz, notlst 286: 5363 47 ld b, a 287: 5364 3A7254 ld a, (dcb+8) 288: 5367 4F ld c, a 289: 5368 0D dec c ; EOF offset 0: write 256 bytes 290: 5369 03 inc bc 291: 536A notlst: 292: 536A 219A54 ld hl, iobuf 293: 536D ED33 defw emt_write 294: 536F C1 pop bc 295: 5370 2805 jr z, wrok 296: 5372 213E54 ld hl, uwrer ; write error 297: 5375 182B jr uerror 298: 5377 79 wrok: ld a, c 299: 5378 B0 or b 300: 5379 20B3 jr nz, loop 301: 302: ;; Close 303: 537B ED31 closit: defw emt_close ; close Unix file 304: 537D 2805 jr z, closok 305: 537F 215454 ld hl, uclser ; close error 306: 5382 181E jr uerror 307: 5384 116A54 closok: ld de, dcb 308: 5387 CD0C52 call close ; close the TRS-80 file 309: 538A 2807 jr z, cls2ok 310: 538C 4F ld c, a 311: 538D CD1852 call error ; oops, i/o error 312: 5390 C32052 jp abort 313: 5393 210000 cls2ok: ld hl, 0 ; all is well 314: 5396 C31C52 jp exit 315: 316: ;; Usage message 317: 5399 210054 usage: ld hl, usager ; error message and exit 318: 539C CD2452 call dsply 319: 539F C32052 jp abort 320: 321: ;; Unix error, msg in hl, errno in a 322: 53A2 F5 uerror: push af 323: 53A3 CD2452 call dsply 324: 53A6 F1 pop af 325: 53A7 219A54 ld hl, iobuf 326: 53AA 010001 ld bc, 256 327: 53AD ED35 defw emt_strerror 328: 53AF CD2452 call dsply 329: 53B2 C32052 jp abort 330: 331: ;; Display message in HL. 03h terminate, 0dh newline and terminate. 332: 53B5 111D40 dsply5: ld de, dodcb$ 333: 53B8 E5 push hl 334: 53B9 7E dsply0: ld a, (hl) 335: 53BA FE03 cp 03h 336: 53BC 280A jr z, dsply1 337: 53BE F5 push af 338: 53BF CD1B00 call @put 339: 53C2 F1 pop af 340: 53C3 23 inc hl 341: 53C4 FE0D cp 0dh 342: 53C6 20F1 jr nz, dsply0 343: 53C8 E1 dsply1: pop hl 344: 53C9 C9 ret 345: 346: ;; Convert (NUL terminated) string in HL to lower case. 347: 53CA E5 lcconv: push hl 348: 53CB 54 ld d, h 349: 53CC 5D ld e, l 350: 53CD 7E lcloop: ld a, (hl) 351: 53CE FE5B cp 5bh ; use '[' or uparrow as escape 352: 53D0 2004 jr nz, lconv1 353: 53D2 23 inc hl 354: 53D3 7E ld a, (hl) 355: 53D4 1809 jr lconv2 ; char after esc: don't convert 356: 53D6 D641 lconv1: sub 'A' 357: 53D8 FE1A cp 26 358: 53DA 7E ld a, (hl) 359: 53DB 3002 jr nc, lconv2 360: 53DD F620 or 20h ; convert to lower case 361: 53DF 12 lconv2: ld (de), a 362: 53E0 23 inc hl 363: 53E1 13 inc de 364: 53E2 B7 or a ; NUL terminator? 365: 53E3 20E8 jr nz, lcloop 366: 53E5 E1 pop hl 367: 53E6 C9 ret 368: 369: ;; EOF handling differs between TRS-80 DOSes: 370: ;; For TRSDOS 2.3 and LDOS, word (dcb+12) contains the number of 371: ;; 256 byte records in the file, byte (dcb+8) contains the EOF 372: ;; offset in the last record (0=256). 373: ;; For NEWDOS/80 and TRSDOS 1.3, byte (dcb+8) and word (dcb+12) 374: ;; form a 24 bit number containing the relative byte address of EOF. 375: ;; Thus (dcb+12) differs by one if the file length is not a 376: ;; multiple of 256 bytes. DOSPLUS also uses this convention, 377: ;; and NEWDOS 2.1 probably does too (not checked). 378: 379: ; Returns number of (partial or full) records in BC, destroys A 380: 53E7 getern5: 381: 53E7 ED4B7654 ld bc, (dcb+12) 382: 53EB 3A5852 ld a, (ernldos) ; get ERN convention 383: 53EE A7 and a 384: 53EF C0 ret nz ; done if TRSDOS 2.3/LDOS convention 385: 53F0 3A7254 ld a, (dcb+8) ; length multiple of 256 bytes? 386: 53F3 A7 and a 387: 53F4 C8 ret z ; done if so 388: 53F5 03 inc bc ; no, # of records = last full record + 1 389: 53F6 C9 ret 390: 391: ; All Model 4 mode operating systems should be TRSDOS/LS-DOS 6.x compatible 392: 53F7 getern6: 393: 53F7 ED4B7654 ld bc, (dcb+12) 394: 53FB C9 ret 395: 396: 53FC 00 lflag: defb 0 397: 53FD 00 nflag: defb 0 398: 53FE 0000 lfname: defw 0 399: 400: 5400 55736167 usager: defb 'Usage: EXPORT [-lne] fromfile [unixfile]', 0dh 653A2045 58504F52 54205B2D 6C6E655D 2066726F 6D66696C 65205B75 6E697866 696C655D 0D 401: 5429 4572726F uopner: defb 'Error in Unix open: ', 03h 7220696E 20556E69 78206F70 656E3A20 03 402: 543E 4572726F uwrer: defb 'Error in Unix write: ', 03h 7220696E 20556E69 78207772 6974653A 2003 403: 5454 4572726F uclser: defb 'Error in Unix close: ', 03h 7220696E 20556E69 7820636C 6F73653A 2003 404: 405: 546A dcb: defs 48 ; 48 for Model III TRSDOS 1.3 406: 549A iobuf: defs 256 407: 408: 5259 end export Statistics: 102 symbols 618 bytes Symbol Table: @abort =4030 emt_read =32ed+ lflag 53fc @abort6 = 15 emt_strerror =35ed lfname 53fe @close =4428 emt_write =33ed loop 532e @close6 = 3c endj 522c lrlerr = 2a @dsply6 = a eo_accmode = 3+ nflag 53fd @error =4409 eo_append = 400+ nlfals 535a @error6 = 1a eo_creat = 40 not4 526d @exit =402d eo_excl = 80+ notlf 5357 @exit6 = 16 eo_rdonly = 0+ notlst 536a @fspec =441c eo_rdwr = 2+ notsl 52f1 @fspec6 = 4e eo_trunc = 200 open 5208 @init =4420 eo_wronly = 1 opn2ok 532b @init6 = 3a ernldos 5258 rdok 5343 @open =4424 error 5218 reed 5210 @open6 = 3b exit 521c startj 5200 @put = 1b export 5259 startj6 522c @read =4436 flag0 527c tloop 5353 @read6 = 43 flag1 5287 uclser 5454 @svc = 28 flag2 52ae uerror 53a2 @write =4439 flag3 528d uname 5311 @write6 = 4b flagl 5299 unix0 52c3 abort 5220 flagn 52a4 unix1 52cd close 520c fromf 52b7 unix2 52d2 closit 537b fspec 5200 uopner 5429 closok 5384 getern 5228 usage 5399 cls2ok 5393 getern5 53e7 usager 5400 dcb 546a getern6 53f7 usetrs 52dc dodcb =401d gotid 5279 ut1 52e2 dsply 5224 gotu 52f8 utdone 52f6 dsply0 53b9 init 5204+ uwrer 543e dsply1 53c8 iobuf 549a write 5214+ dsply5 53b5 lcconv 53ca wrok 5377 emt_close =31ed lcloop 53cd emt_lseek =34ed+ lconv1 53d6 emt_open =30ed lconv2 53df