xasm/xboot.asm

631 lines
11 KiB
NASM

; ><-B00T V b. Fox
IDEAL
P386
MODEL TINY
CODESEG
zero db 100h dup(?)
blen = 59*1024
m_pro = 1 ; /p switch
m_errs = 2 ; error/warning occured while current file
m_file = 4 ; single file (atr name for one file given)
m_lfn = 8 ; LFN search
eol equ 13,10
eot equ 13,10,'$'
struc finddata16
db 21 dup(?)
attr db ?
time dw ?
date dw ?
fsize dd ?
fname db 13 dup(?)
ends
struc filetime32
dd ?,?
ends
struc finddata32
attr dd ?
creat filetime32 ?
acces filetime32 ?
write filetime32 ?
fsizeh dd ?
fsizel dd ?
dd ?,?
fname db 260 dup(?)
aname db 14 dup(?)
ends
MACRO lda _rg ; shorter than 'mov (e)ax, _rg'
_rge SUBSTR <_rg>, 1, 1
IFIDNI _rge, <e>
xchg eax, _rg
ELSE
xchg ax, _rg
ENDIF
ENDM
MACRO sta _rg ; shorter than 'mov _rg, (e)ax'
_rge SUBSTR <_rg>, 1, 1
IFIDNI _rge, <e>
xchg _rg, eax
ELSE
xchg _rg, ax
ENDIF
ENDM
MACRO dos _func ; call DOS function
IFNB <_func>
IF _func and 0ff00h
mov ax, _func
ELSE
mov ah, _func
ENDIF
ENDIF
int 21h
ENDM
MACRO file _func
IFNB <_func>
IF _func and 0ff00h
mov ax, _func
ELSE
mov ah, _func
ENDIF
ENDIF
call xdisk
ENDM
MACRO jfile _func
IFNB <_func>
IF _func and 0ff00h
mov ax, _func
ELSE
mov ah, _func
ENDIF
ENDIF
jmp xdisk
ENDM
MACRO print _text ; print ascii$ text
IFNB <_text>
mov dx, offset _text
ENDIF
dos 9
ENDM
start:
db 1536 dup(0) ; COMpack sux
mov [spt], sp
print hello
; Get arguments: obxnam, atrnam & /p switch
; Set onam & anam to end of filenames
mov si, 81h
mov bx, offset onam
arg1: lodsb
cmp al, ' '
je arg1 ; skip spaces
cmp al, '-'
je swit
cmp al, '/'
jne nswit
; Switch
swit: lodsb
and al, 0dfh
cmp al, 'P'
jne usg
or [flags], m_pro ; '/P'
jmp arg1
nswit: cmp al, 0dh
je argx
; Filename
cmp bx, offset enam
jae usg ; two names already parsed
mov di, [bx]
mov ah, '"'
cmp al, ah
je qname ; "file name with spaces"
mov ah, ' '
gname: stosb ; copy name
qname: lodsb
cmp al, ah ; space/'"', eol and '/' terminate name
je xname
cmp al, 0dh
je bname
cmp al, '/'
jne gname
bname: dec si
xname: mov [bx], di ; save end of name ptr
inc bx
inc bx
mov [byte di], 0
jmp arg1
; Usage
usg: print usgtxt
dos 4c03h
; End of arguments
argx: cmp bx, offset anam
jb usg ; no obxnam given
; Find where obx FILE name begins
mov di, [onam]
lea cx, [di+1+zero-obxnam]
fofna1: dec di
cmp [byte di], '\'
je fofnax
cmp [byte di], ':'
loopne fofna1
fofnax: inc di
mov [ofna], di
; Is atr given?
cmp bx, offset anam
ja atrgvn ; atr given
; Only obx given
; Move path of obx to atrnam
mov si, offset obxnam
mov di, offset atrnam
mobat1: lodsb
stosb
cmp al, '\'
je mobat2
cmp al, ':'
jne mobat3
mobat2: mov [anam], di
mobat3: test al, al
jnz mobat1
mov di, [anam]
mov [byte di], 0
jmp srvobx
; Atr given
; Delete trailing '\' if not "\" or "C:\"
atrgvn: mov di, [anam]
dec di
cmp [byte di], '\'
jne atrg1
mov [anam], di
cmp di, offset atrnam
jbe atrg1
cmp [byte di-1], ':'
je atrg1
mov [byte di], 0
atrg1:
; Check if it is file or dir
mov dx, offset atrnam
xor bx, bx ; try LFN function
stc
dos 7143h
jnc chkafd
cmp ax, 7100h ; LFN not supported
jne afile ; possibly file/dir doesn't exist -> file
dos 43h ; call MS-DOS function 4300h
jc afile ; failed -> file
chkafd: test cl, 10h
jnz adir
; It is file
; Add .atr extension, if none
afile: or [flags], m_file
mov di, [anam]
lea cx, [di+zero-atrnam]
mov eax, 'rta.'
call adext
jmp srvobx
; It is dir
; Add trailing '\'
adir: mov di, [anam]
mov [byte di], '\'
inc [anam]
; Serve obx
; Add .obx extension, if none
srvobx: mov di, [onam]
lea cx, [di+zero-obxnam]
mov eax, 'xbo.'
call adext
; Find first file
mov dx, offset obxnam
mov cx, 7 ; try LFN
mov si, 1
mov di, offset f32
stc
dos 714eh
jnc flfn
cmp ax, 7100h ; LFN not supported
jne nofil
xor cx, cx ; call MS-DOS function 4Eh
dos 4eh
jnc main1
nofil: print e_nofil ; "No file found"
dos 4c02h
flfn: or [flags], m_lfn ; LFN successfull
mov [fhand], ax
; Main loop - convert found file
main1: and [flags], not m_errs
mov [ohand], 0
mov [ahand], 0
mov [len], lodlen+endlen
; Move name from finddata to obxnam
mov si, offset (finddata16 80h).fname
test [flags], m_lfn
jz nolfn1
mov si, offset f32.fname
nolfn1: mov di, [ofna]
mona1: lodsb
stosb
test al, al
jnz mona1
; Print "file.obx"
mov si, offset obxnam
call printz
; Open obx for reading
mov bp, offset e_open
mov dx, offset obxnam ; MS-DOS
mov ax, 3d00h
test [flags], m_lfn
jz nolfn2
mov si, dx ; LFN
xor bx, bx
mov dx, 1
mov ax, 716ch
nolfn2: file
mov [ohand], ax
; Check if Atari executable
call xreadh
jb enate
cmp [head], -1
jne enate
mov dx, offset head
mov cx, 4
call xread
jnb nenate
enate: mov dx, offset e_nota
jmp error
nenate:
; Set default run address at first block
mov ax, [head]
mov [l1runl], al
mov [l2runl], al
mov [l1runh], ah
mov [l2runh], ah
; Print "->"
print arrow
; Atr FILE name given?
test [flags], m_file
jnz sfile
; No: move name from obx, replacing extension with ".atr"
mov si, [ofna]
mov di, [anam]
mona2: lodsb
stosb
cmp al, '.'
jne mona2
mov eax, 'rta'
stosd
sfile:
; Print "file.atr"
mov si, offset atrnam
call printz ; file.atr
; Create atr file
mov bp, offset e_creat
mov dx, offset atrnam
xor cx, cx
mov ax, 3c00h
test [flags], m_lfn
jz nolfn3
mov si, dx
mov bx, 1
mov dx, 12h ; create or truncate
mov ax, 716ch
nolfn3: file
mov [ahand], ax
; Print "..."
print kropki
; Write atr header
mov cx, beglen
mov dx, offset begin
call xwrite
; Write loader in boot sector
mov cx, lodlen
mov dx, offset stdlod
test [flags], m_pro
jz stlo
mov dx, offset prolod
stlo: call xwrite
jmp firs
; Converting
; Read obx header
skff: call xreadh
jb chtrun
cmp [head], -1
je skff
mov dx, offset head+2
call xread2
jb trunca
; Read block
firs: mov cx, [head+2]
sub cx, [head]
inc cx
cmp cx, blen
jbe okhead
mov cx, blen
okhead: mov dx, offset blok
call xread
jb trunc
; Write
call xwrihd
jmp skff
; Check if block is truncated
chtrun: test ax, ax
jnz trunca
jmp finfil
trunc: test ax, ax
jz finfil
dec ax
push ax
add ax, [head]
mov [head+2], ax
pop ax
call xwrihd
trunca: mov dx, offset w_trunc
; Warning
warfin: call warni
; End of file
; Write endsequence
finfil: mov dx, offset endseq1
test [flags], m_pro
jz endst
mov dx, offset endseq2
endst: mov cx, endlen
call xwrite
mov cx, 40h
xor ax, ax
mov di, offset head
rep stosw
sta cx
sub cl, [byte len]
and ecx, 7fh
jz fuls
call xwrith
fuls:
; Write number of paragraphs (para=16 bytes) to atr
xor cx, cx ; seek back to para's atr header field
mov dx, 2
mov bp, offset e_write
file 4200h
shr [len], 4
mov cx, 2
mov dx, offset len
call xwrite
; Close files
shut: mov bx, [ahand]
mov bp, offset e_write
call xclose
mov bx, [ohand]
mov bp, offset e_read
call xclose
test [flags], m_errs
jnz nook
print oktxt
nook: print eoltxt
; Find next file
test [flags], m_lfn
jnz lfnnx
dos 4fh ; MS-DOS function
jc fin
nexfil: test [flags], m_file
jnz singl
jmp main1
lfnnx: mov bx, [fhand] ; LFN function
mov si, 1
mov di, offset f32
dos 714fh
jnc nexfil
dos 71a1h ; LFN search close
fin: mov ax, [exitcod]
dos
singl: print e_singl
dos 4c02h
; Add extension if none (di=end of name, cx=len, eax=ext)
adext: mov bx, di
adext1: dec bx
cmp [byte bx], '.'
je adextr
cmp [byte bx], '\'
loopne adext1
stosd
adextr: mov [byte di], 0
ret
xdisk: push bp
dos
pop dx
jnc rts
error: mov sp, [spt]
mov [byte exitcod], 2
or [flags], m_errs
print
jmp shut
warni: cmp [byte exitcod], 1
jae nwacod
mov [byte exitcod], 1
nwacod: or [flags], m_errs
print
ret
xreadh: mov dx, offset head
xread2: mov cx, 2
xread: mov bx, [ohand]
mov bp, offset e_read
file 3fh
cmp ax, cx
rts: ret
xwrihd: add ax, 4
movzx ecx, ax
mov ax, [head]
mov dx, [head+2]
test [flags], m_pro
jnz chkpro
cmp ah, 8
jae chkst1
cmp dh, 7
jae ememc
chkst1: cmp dh, 0c0h
jb xwrith
cmp dh, 0d0h
jb eproc
cmp ah, 0d8h
jb xwrith
eproc: mov dx, offset w_prof
jmp xwwarn
chkpro: cmp ah, 5
jae xwrith
cmp dh, 4
jb xwrith
ememc: mov dx, offset w_mem
xwwarn: push ecx
call warni
pop ecx
xwrith: mov dx, offset head
xwritl: add [len], ecx
xwrite: mov bx, [ahand]
mov bp, offset e_write
jfile 40h
xclose: test bx, bx
jz rts
jfile 3eh
pnam1: sta dx
dos 2
printz: lodsb
test al, al
jnz pnam1
ret
hello db 'X-BOOT 5.0 by Fox/Taquart',eot
usgtxt db 'Converts Atari 8-bit executables to .ATR disk images.',eol
db 'Syntax: XBOOT [/p] obxfiles [atrpath][atrfile]',eol
db '/p Write professional loader rather than standard.'
eoltxt db eot
arrow db ' -> $'
kropki db ' ... $'
oktxt db 'OK$'
w_mem db eol,' WARNING: Memory conflict$'
w_prof db eol,' WARNING: Professional loader needed$'
w_trunc db eol,' WARNING: File is truncated$'
e_nofil db 'ERROR: File not found',eot
e_singl db 'ERROR: Single target for many files',eot
e_nota db eol,' ERROR: Not Atari executable$'
e_open db eol,' ERROR: Can''t open file$'
e_read db eol,' ERROR: Disk read error$'
e_creat db eol,' ERROR: Can''t create file$'
e_write db eol,' ERROR: Disk write error$'
; ATR Header
begin dw 296h,0,80h,4 dup(0)
db 0,1
beglen = $-begin
; Loader #1 (std)
stdlod db 0,1,128,7,119,228,160,215,185,27,7,145,88,200,192,226,144
db 246,169
l1runl db 168,141,224,2,169
l1runh db 7,141,225,2,169,7,141,5,3,169,255
db 141,1,211,173,56,96,169,7,141,227,2,72,169,168,141,226,2,72
db 162,251,149,72,232,134,67,238,210,7,16,16,238,10,3,208,3,238
db 11,3,32,83,228,48,217,14,210,7,173,127,7,166,67,208,223,129
db 68,230,68,208,2,230,69,165,70,197,68,165,71,229,69,176,210,169
db 3,141,15,210,108,226,2,44,111,97,100,105,110,103,14,14,14,0
db 53,46,48
lodlen = $-stdlod
; Ending Header for loader #1
endseq1 db 240,7,240,7,224
endlen = $-endseq1
; Loader #2 (rom)
prolod db 0,1,128,4,119,228,169,0,141,47,2,169,82,141,200,2,165
db 20,197,20,240,252,169
l2runl db 162,141,224,2,169
l2runh db 4,141,225,2,173,56,96
db 169,4,141,227,2,72,169,162,141,226,2,72,162,251,149,72,232,134
db 67,238,220,4,16,32,238,10,3,208,3,238,11,3,169,255,141,1
db 211,78,14,212,88,32,83,228,48,208,120,238,14,212,206,1,211,14
db 220,4,173,127,4,166,67,208,207,129,68,230,68,208,2,230,69,165
db 70,197,68,165,71,229,69,176,194,169,3,141,15,210,108,226,2,53
db 46,48,112
; Ending Header for loader #2
endseq2 db 250,4,250,4,224
exitcod dw 4c00h
flags db 0
len dd lodlen+endlen
onam dw obxnam
anam dw atrnam
enam:
fhand dw ?
ohand dw ?
ahand dw ?
ofna dw ?
spt dw ?
obxnam db 100h dup(?)
atrnam db 100h dup(?)
f32 finddata32 ?
head dw ?,?
blok db blen dup(?)
ENDS
END start