1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
|
;; export.z
;; Timothy Mann, 8/24/97
;; $Date: 2006/05/15 00:48:57 $
;;
;; Copyright (c) 1997, Timothy Mann
;;
;; This software may be copied, modified, and used for any
;; purpose without fee, provided that (1) the above copyright
;; notice is retained, and (2) modified versions are clearly
;; marked as having been modified, with the modifier's name and
;; the date included.
;;
;; Use xtrs emulator traps to copy a file from TRS-80 to Unix
;; Usage: EXPORT [-lne] fromfile [unixfile]
;; Parameter -l will convert the Unix file to lower case.
;; (Needed for NEWDOS/80. They insist on uppercasing the command line.)
;; If the -n parameter is given, each carriage return ('\r')
;; in the TRS-80 file is converted to a newline ('\n') in the Unix file.
;; The program tries to determine what DOS it is running on and use
;; the correct FCB end of file convention, but this works only on
;; TRSDOS, LDOS, and NEWDOS/80. For other DOSes that use the
;; NEWDOS/80 convention (such as DOSPLUS), give the -e paramter.
;; If the unixfile parameter is omitted, the fromfile parameter is used,
;; with '/' changed to '.'.
;; Model I/III addresses
@fspec equ 441ch
@init equ 4420h
@open equ 4424h
@close equ 4428h
@read equ 4436h
@write equ 4439h
@error equ 4409h
@exit equ 402dh
@abort equ 4030h
@put equ 001bh
dodcb$ equ 401dh
;; Model 4 SVCs
@svc equ 40 ; rst address for SVCs
;@svc equ 5 ; older zmac requires 8080-style "rst 5"
@fspec6 equ 78
@init6 equ 58
@open6 equ 59
@close6 equ 60
@read6 equ 67
@write6 equ 75
@error6 equ 26
@exit6 equ 22
@abort6 equ 21
@dsply6 equ 10
;; Model 4 only: file init or open with wrong LRL. Can be ignored.
lrlerr equ 42
org 5200h
;; Jump tables for OS independence
startj:
fspec: call @fspec
ret
init: call @init
ret
open: call @open
ret
close: call @close
ret
reed: call @read
ret
write: call @write
ret
error: call @error
ret
exit: call @exit
ret
abort: call @abort
ret
dsply: call dsply5
ret
getern: call getern5
ret
endj:
; Model 4
startj6:
ld a, @fspec6
rst @svc
ret
ld a, @init6
rst @svc
ret
ld a, @open6
rst @svc
ret
ld a, @close6
rst @svc
ret
ld a, @read6
rst @svc
ret
ld a, @write6
rst @svc
ret
ld a, @error6
rst @svc
ret
ld a, @exit6
rst @svc
ret
ld a, @abort6
rst @svc
ret
ld a, @dsply6
rst @svc
ret
call getern6
ret
; Nonzero for LDOS ern convention
ernldos: db 1
; Emulator trap instructions, byte-reversed for use in defw:
emt_open equ 30edh
emt_close equ 31edh
emt_read equ 32edh
emt_write equ 33edh
emt_lseek equ 34edh
emt_strerror equ 35edh
EO_ACCMODE equ 3q
EO_RDONLY equ 0q
EO_WRONLY equ 1q
EO_RDWR equ 2q
EO_CREAT equ 100q
EO_EXCL equ 200q
EO_TRUNC equ 1000q
EO_APPEND equ 2000q
export:
ld a, (000ah) ; Model 4?
cp 40h
jr z, not4
push hl
ld de, startj
ld hl, startj6
ld bc, endj - startj
ldir
pop hl
not4:
ld a, (4427h) ; system id for Newdos/80...
sub 82h ; ...should be 82h (v2.0)
jr z, gotid
ld a, (441fh) ; system version number for most other DOSes
sub 13h ; TRSDOS 1.3?
gotid: ld (ernldos), a
flag0: ld a, (hl) ; look for flags
cp ' '
jp c, usage ; error if line ends here
jr nz, flag1
inc hl
jr flag0
flag1: cp '-'
jr nz, fromf
inc hl
ld a, (hl)
flag3: or 20h
cp 'e'
jr nz, flagl
sub a
ld (ernldos), a
jr flag2
flagl: cp 'l'
jr nz, flagn ; check for next flag
ld a, 1
ld (lflag), a
jr flag2
flagn: cp 'n'
jp nz, usage ; unknown flag
ld a, 1
ld (nflag), a
flag2: inc hl
ld a, (hl)
cp ' '
jr nz, flag3 ; another flag follows
inc hl
jr flag0
fromf: ld de, dcb ; ready to get LDOS filename from (HL)
ld (lfname), hl ; save if needed to default Unix name
call fspec
jp nz, usage
unix0: ld a, (hl) ; scan over Unix filename
cp ' ' ; first skip spaces
jr c, usetrs ; if no Unix name, use translated TRS name
jr nz, unix1
inc hl
jr unix0
unix1: ld de, iobuf ; copy Unix filename
ld a, ' '
unix2: cp (hl)
ldi
jr c, unix2
dec de
sub a
ld (de), a ; NUL terminate Unix name
jr gotu
usetrs: ld hl, (lfname) ; translate TRS-80 name to Unix
ld de, iobuf
ut1: ld a, (hl)
cp ':' ; drivespec?
jr z, utdone ; done if so
cp ' '+1 ; end of line?
jr c, utdone ; done if so
cp '/' ; change '/' to '.' for extension
jr nz, notsl
ld a, '.'
notsl: ld (de), a
inc hl
inc de
jr ut1
utdone: sub a ; NUL-terminate Unix name
ld (de), a
gotu: ld hl, iobuf
ld de, dcb
ld b, 0
call open ; open the TRS-80 file
pop hl
jr z, uname
cp lrlerr
jr z, uname
ld c, a
call error
jp abort
uname: ld hl, iobuf ; path
ld a, (lflag)
or a
call nz, lcconv ; convert filename to lower case
ld bc, EO_WRONLY|EO_CREAT|EO_TRUNC
ld de, 0666q ; mode
defw emt_open ; open the Unix file
jr z, opn2ok ; go if OK
ld hl, uopner ; error message and exit
jp uerror
;; Read
opn2ok: call getern ; count down records in bc
loop: push de ; save fd
ld de, dcb
call reed ; read 256 bytes from file
pop de
jr z, rdok ; got a full 256 bytes
cp 28 ; eof?
jr z, closit ; yes, OK
ld c, a
call error ; oops, i/o error
jp abort
rdok: dec bc
;; Translate
push bc ; save record count
ld a, (nflag) ; check for NL feature
and a
jr z, nlfals
ld hl, iobuf
ld a, 0dh
ld bc, 000ah ; b := 0, c := 0ah
tloop: cp (hl)
jr nz, notlf
ld (hl), c
notlf: inc hl
djnz tloop
nlfals: pop bc ; restore record count
;; Write
ld a, c
or b ; last record?
push bc ; save record count
ld bc, 0100h ; byte count
jr nz, notlst
ld b, a
ld a, (dcb+8)
ld c, a
dec c ; EOF offset 0: write 256 bytes
inc bc
notlst:
ld hl, iobuf
defw emt_write
pop bc
jr z, wrok
ld hl, uwrer ; write error
jr uerror
wrok: ld a, c
or b
jr nz, loop
;; Close
closit: defw emt_close ; close Unix file
jr z, closok
ld hl, uclser ; close error
jr uerror
closok: ld de, dcb
call close ; close the TRS-80 file
jr z, cls2ok
ld c, a
call error ; oops, i/o error
jp abort
cls2ok: ld hl, 0 ; all is well
jp exit
;; Usage message
usage: ld hl, usager ; error message and exit
call dsply
jp abort
;; Unix error, msg in hl, errno in a
uerror: push af
call dsply
pop af
ld hl, iobuf
ld bc, 256
defw emt_strerror
call dsply
jp abort
;; Display message in HL. 03h terminate, 0dh newline and terminate.
dsply5: ld de, dodcb$
push hl
dsply0: ld a, (hl)
cp 03h
jr z, dsply1
push af
call @put
pop af
inc hl
cp 0dh
jr nz, dsply0
dsply1: pop hl
ret
;; Convert (NUL terminated) string in HL to lower case.
lcconv: push hl
ld d, h
ld e, l
lcloop: ld a, (hl)
cp 5bh ; use '[' or uparrow as escape
jr nz, lconv1
inc hl
ld a, (hl)
jr lconv2 ; char after esc: don't convert
lconv1: sub 'A'
cp 26
ld a, (hl)
jr nc, lconv2
or 20h ; convert to lower case
lconv2: ld (de), a
inc hl
inc de
or a ; NUL terminator?
jr nz, lcloop
pop hl
ret
;; EOF handling differs between TRS-80 DOSes:
;; For TRSDOS 2.3 and LDOS, word (dcb+12) contains the number of
;; 256 byte records in the file, byte (dcb+8) contains the EOF
;; offset in the last record (0=256).
;; For NEWDOS/80 and TRSDOS 1.3, byte (dcb+8) and word (dcb+12)
;; form a 24 bit number containing the relative byte address of EOF.
;; Thus (dcb+12) differs by one if the file length is not a
;; multiple of 256 bytes. DOSPLUS also uses this convention,
;; and NEWDOS 2.1 probably does too (not checked).
; Returns number of (partial or full) records in BC, destroys A
getern5:
ld bc, (dcb+12)
ld a, (ernldos) ; get ERN convention
and a
ret nz ; done if TRSDOS 2.3/LDOS convention
ld a, (dcb+8) ; length multiple of 256 bytes?
and a
ret z ; done if so
inc bc ; no, # of records = last full record + 1
ret
; All Model 4 mode operating systems should be TRSDOS/LS-DOS 6.x compatible
getern6:
ld bc, (dcb+12)
ret
lflag: defb 0
nflag: defb 0
lfname: defw 0
usager: defb 'Usage: EXPORT [-lne] fromfile [unixfile]', 0dh
uopner: defb 'Error in Unix open: ', 03h
uwrer: defb 'Error in Unix write: ', 03h
uclser: defb 'Error in Unix close: ', 03h
dcb: defs 48 ; 48 for Model III TRSDOS 1.3
iobuf: defs 256
end export
|