babelfish_applesoft/init.asm

1403 lines
14 KiB
NASM

;
; AppleSoft BASIC BabelFish importer 1.0
; by Kelvin Sherlock
;
; For educational purposes only
;
;
case off
mcopy init.mac
copy 13:Ainclude:e16.gsos
copy bfish.equ
BAS_FTYPE gequ $FC
BAS_ATYPE gequ $0801
SHASTON_ID gequ $fffe
;
; This is the entry point.
;
init START
using global
phb
phk
plb
;
; Get my memory manager ID
;
pha
_MMStartUp
pla
sta MyID
;
; convert it to english & tack on to the end of my request name
;
pha ;; MyID
pea MyName|-16
pea MyName+28
pea 4
_Int2Hex
;
; Accept Requests
;
pea MyName|-16
pea MyName
lda MyID
pha
pea RequestH|-16
pea RequestH
_AcceptRequests
;
; leave (for now)
;
plb
rtl
init END
global DATA
MyName pstr "Babelfish~Kelvin~ASoftTransXXXX"
BName pstr "Seven Hills~Babelfish~"
CalcStr pstr "Calculating Space Requirements"
TokeStr pstr "Detokenizing file"
DoneStr pstr "Done!"
InRec ds 4
OutRec ds 4 ;; space for BFProgress
MyID ds 2
Active ds 2
Done ds 2
FileHandle ds 4
;
; Text Record
;
Text_pCount dc i2'10'
Text_ActionCode ds 2
Text_ResponseCode ds 2
Text_Length ds 4
Text_Ptr ds 4
Text_Hnd ds 4
Text_FamilyID dc i2'SHASTON_ID'
Text_FontSize dc i2'8'
Text_FontStyle dc i2'0'
Text_ForeColor dc i2'0'
Text_BackColor dc i2'$ffff'
OpenDCB anop
OpenDCB_pcount dc i2'15'
OpenDCB_refNum ds 2
OpenDCB_pathName dc i4'0'
OpenDCB_requestAccess ds 2
OpenDCB_resourceNumber dc i2'0'
OpenDCB_access ds 2
OpenDCB_fileType ds 2
OpenDCB_auxtype ds 4
OpenDCB_storageType ds 2
OpenDCB_createDateTime ds 8
OpenDCB_modDateTime ds 8
OpenDCB_optionList ds 4
OpenDCB_dataEOF ds 4
OpenDCB_blocksUsed ds 4
OpenDCB_resourceEOF ds 4
OpenDCB_resourceBlocks ds 4
;
; for reading/writing data
;
IODCB anop
IODCB_pcount dc i2'5'
IODCB_refNum ds 2
IODCB_dataBuffer ds 4
IODCB_requestCount ds 4
IODCB_transferCount ds 4
IODCB_cachePriority dc i4'0'
CloseDCB dc i2'1'
CloseDCB_refnum ds 2
global END
;
; Request Handler (called by application via bfish via toolbox)
;
; in stack out stack
; |------------ |-----------
; | result | result 0 = not accepted, $8000 = accepted
; |------------ |-----------
; | request
; |------------
; |
; | DataIn
; |
; |------------
; |
; | DataOut
; |
; |------------
; |
; | rtl
; |------------
RequestH START
using Global
result equ 17
reqCode equ 15
dataIn equ 11
dataOut equ 7
_rtlb equ 3
_d equ 1
phb
phk
plb
phd
tsc
tcd
;
; this should be zeroed already, but better safe than sorry
;
stz <result
;
; Check what sort of request it is
;
lda <reqCode
cmp #TrStartUp
bne n1
lda #$8000 ; yes, I'll handle it
sta <result
ldy #2
lda [<DataIn],y
pha
lda [<DataIn]
pha
jsr DoStartUp
ldy #2
sta [DataOut],y ; error to bfish
bra exit
n1 anop
cmp #TrShutDown
bne n2
lda #$8000 ; yes, I'll accept it
sta <result
jsr DoShutDown
ldy #2
sta [DataOut],y
bra exit
n2 anop
cmp #TrRead
bne exit
lda #$8000 ; yes, I'll accept it
sta <result
ldax <DataIn
stax InRec
ldy #2
lda [<DataIn],y
pha
lda [<DataIn]
pha
jsr DoRead
ldy #2
sta [DataOut],y
exit anop
pld ;restore the old dpage
pla ; move rtlb
sta 9,s
pla
sta 9,s
pla
pla
pla
plb
rtl
RequestH END
;
; Startup procedure
;
; returns a = 0 on success, a = errno on failure
DoStartUp START
using Global
_d equ 1
_rts equ 3
xPtr equ 5
phd
tsc
tcd
stz Active
stz Done
stz FileHandle
stz FileHandle+2
;
; Tell the reciever that we will export as text
;
;
lda #bffText
ldy #offset_DataKinds
sta [xPtr],y
;
; Open the file
;
lda #readEnable
sta OpenDCB_requestAccess
ldy #offset_FilePathPtr+2
lda [xPtr],y
sta OpenDCB_pathName+2
dey
dey
lda [xPtr],y
sta OpenDCB_pathName
_OpenGS OpenDCB
bcc *+5
brl exit ;;return GSOS error
lda OpenDCB_refNum
sta CloseDCB_refNum
sta IODCB_refNum
lda OpenDCB_fileType
cmp #BAS_FTYPE
bne wrong_type
lda OpenDCB_auxType
cmp #BAS_ATYPE
beq right_type
wrong_type anop
_CloseGS CloseDCB
lda #bfBadFileErr
ldy #offset_Status
sta [xPtr],y
lda #$ffff
brl exit
right_type anop
;
; AppleSoft files BETTER be < 65,535 bytes long!
;
lda OpenDCB_dataEOF+2
bne wrong_type
;
; Set the thermometer values
;
lda #2
ldy #offset_FullTherm
sta [xPtr],y
lda #0
ldy #offset_CurrentTherm
sta [xPtr],y
;
; set the Data Record Ptr
;
ldy #offset_DataRecordPtr
lda #Text_pCount
sta [xPtr],y
iny
iny
lda #^Text_pCount
sta [xPtr],y
;
; initialize the text record
;
lda #0
sta Text_Ptr
sta Text_Ptr+2
sta Text_Length
sta Text_Length+2
sta Text_Hnd
sta Text_Hnd+2
sta Text_ForeColor ;;black = 0
lda #10 ;; # of parms
sta Text_pCount
lda #SHASTON_ID
sta Text_FamilyID
lda #8
sta Text_FontSize
lda #$ffff
sta Text_BackColor
;
; GetSettings
;
lda #1
sta Text_ActionCode
exl inc Active
lda #0
exit anop
pld
ply ;return address
plx ;args on the stack
plx
phy ;restore the return address
rts
END
;
; DoShutDown - prepare to go away
;
; returns a = 0 on success, a = errno on failure (yeah, right)
DoShutDown START
using Global
lda Active
beq exit
_CloseGS CloseDCB
exit lda #0
rts
END
;
; DoRead - the meat & potatoes
;
; returns a = 0 on success, a = errno on failure
DoRead START
using Global
_d equ 1
FilePtr equ 3 ; locals
OutPtr equ 7
Length equ 11
pstrPtr equ 15
_rts equ 19
xPtr equ 21 ; passed on stack
;
; Create some local vars
;
tsc
sec
sbc #16
tcs
phd
tsc
tcd
;
; Done is our status so I know what I'm doing :)
;
; 0 = get defaults from application
; 1 = detokenize the file
; 2 = all done
lda Done
bne part2
;
; Get defaults for the text record from the application
;
lda #1 ;request defaults
sta Text_ActionCode
lda #bfContinue
ldy #offset_Status
sta [xPtr],y
inc Done
lda #0
brl exit
part2 cmp #1
beq convert
; ok, were done, so say so & exit
lda #bfDone
ldy #offset_Status
sta [xPtr],y
lda #0
brl exit
convert anop
stz Text_ActionCode
;
; File was opened w/ startup
; Now, read the file
;
ldax OpenDCB_dataEOF
stax IODCB_requestCount
stax <Length
;
; Allocate 4 extra bytes, so I can fill them in w/ 0s to be safe
;
clc
adc #4
bcc f2
inx
f2 anop
pha ;;space
pha
phxa ;;size
lda MyID
pha ;;MemID
pea $c008 ;;attr: locked, fixed, no spec.
pea 0 ;;location
pea 0
_NewHandle
tay
plax
stax <FilePtr
stax FileHandle
bcc read_it
phy ;;save error
ldy #offset_Status
lda #bfMemErr
sta [xPtr],y
pla ;;error code from toolbox
brl exit
read_it anop
;
; deref the handle
;
ldy #2
lda [FilePtr],y
tax
lda [FilePtr]
stax <FilePtr
stax IODCB_dataBuffer
_ReadGS IODCB
bcc been_read
pha ;store error
;
; Deallocate the memory
;
ldax FileHandle
phxa
_DisposeHandle
ldy #offset_Status
lda #bfReadErr
sta [xPtr],y
pla ;;restore
brl exit
;
; The file has now been read into memory
;
;
been_read anop
;
; Tack 4 0s at the end of the memory. This guarantees
; that I won't overrun the buffer into infinity if it's a
; corruptes file or not even an applesoft file
;
pei FilePtr+2
pei FilePtr
lda OpenDCB_dataEOF
jsr Append0
;
; make it show my message
;
ldy #offset_ProgressAction
lda #1+2+4+8
sta [xptr],y
ldy #offset_MiscFlags
lda #1+2+4
sta [xptr],y
ldy #offset_MsgPtr+2
lda #^CalcStr
sta [xPtr],y
dey
dey
lda #CalcStr
sta [xPtr],y
pea BFProgress ;reqcode
pea $8001 ;sendtoname+stopafterone
pea BName|-16 ;target
pea BName
ldax InRec
phxa
pea OutRec|-16 ;out
pea OutRec
_SendRequest
;
; Calculate the length of the file
;
pei FilePtr+2
pei FilePtr
jsr CalcLength
stax <Length
stax Length2
;
; Add space to include "\nSAVE xxxxx"
;
lda #6 ;; length of "\nSAVE "
clc
adc Length2
sta Length2
bcc a_a
inc Length2+2
a_a ldy #offset_FileNamePtr ;;pstring ptr
lda [xPtr],y
sta <pStrPtr
iny
iny
lda [xPtr],y
sta <pStrPtr+2
lda [<pStrPtr] ;;pstring
and #$00ff
clc
adc Length2
sta Length2
bcc a_b
inc Length2+2
a_b anop
;
; Store the length of data I'm returning
;
ldax Length2
stax Text_Length
;
; allocate memory to return the text in
;
pha
pha
ldax Length2
phxa
lda MyID
pha
pea $c008
pea 0
pea 0
_NewHandle
tay
plax
stax <OutPtr
bcc p1
phy
lda #bfMemErr
ldy #offset_Status
sta [xPtr],y
ldax FileHandle
phxa
_DisposeHandle
pla
brl exit
p1 anop
;
; Store the Handle
;
stax Text_Hnd
;
; Deref Handle->Ptr
;
ldy #2
lda [OutPtr],y
tax
lda [OutPtr]
stax <OutPtr
;
; store the ptr to return
;
stax Text_Ptr
;
; update the thermometer
;
lda #1
ldy #offset_CurrentTherm
sta [xPtr],y
ldy #offset_ProgressAction
lda #1+2+4+8
sta [xptr],y
ldy #offset_MiscFlags
lda #1+2+4
sta [xptr],y
ldy #offset_MsgPtr+2
lda #^TokeStr
sta [xPtr],y
dey
dey
lda #TokeStr
sta [xPtr],y
pea BFProgress ;reqcode
pea $8001 ;sendtoname+stopafterone
pea BName|-16 ;target
pea BName
ldax InRec
phxa
pea OutRec|-16 ;out
pea OutRec
_SendRequest
;
; detokenize the file
;
pei <FilePtr+2
pei <FilePtr
pei <OutPtr+2
pei <OutPtr
jsr ConvertFile
ldax FileHandle
phxa
_DisposeHandle
;
; Now tack on "\nSAVE filename"
;
;
;
; 1) Set OutPtr to the end of the text
;
lda <Length
clc
adc <OutPtr
sta <OutPtr
lda <Length+2
adc <OutPtr+2
sta <OutPtr+2
;
; 2) Tack on "\nSAVE "
;
lda #$0d+256*'S' ;;'\rS'
sta [<OutPtr]
ldy #2
lda #'VA'
sta [<OutPtr],y
iny
iny
lda #' E'
sta [<OutPtr],y
lda #5
clc
adc <OutPtr
sta <OutPtr
bcc a_c
inc <OutPtr+2
;
; 3) Add on the name itself
;
a_c anop
lda #0
short m
lda [<pStrPtr] ;;pstring
tay ;;length of pstring
lp anop
lda [<pStrPtr],y
sta [<OutPtr],y
dey
bne lp
a_d anop
long m
exit_ok anop
;
; update the thermometer
;
lda #2
ldy #offset_CurrentTherm
sta [xPtr],y
ldy #offset_ProgressAction
lda #1+2+4+8
sta [xptr],y
ldy #offset_MiscFlags
lda #1+2+4
sta [xptr],y
ldy #offset_MsgPtr+2
lda #^DoneStr
sta [xPtr],y
dey
dey
lda #DoneStr
sta [xPtr],y
pea BFProgress ;reqcode
pea $8001 ;sendtoname+stopafterone
pea BName|-16 ;target
pea BName
ldax InRec
phxa
pea OutRec|-16 ;out
pea OutRec
_SendRequest
lda #bfContinue
ldy #offset_Status
sta [xPtr],y
lda #0
inc Done
exit anop
pld
tax ;;save
tsc
clc
adc #16
tcs
txa ;;restore
ply ;;_rts
plx ;;passed parameter
plx
phy ; y = return address
rts
Length2 ds 4
DoRead END
;
; int IntLength
;
; determines how much space an integer would take up as a string,
; including a trailing space
;
;
; in: a = the number
; out: a = the length of a string that could represent it
IntLength START
phx ;save
ldx #1
cmp #10
bcc done
inx
cmp #100
bcc done
inx
cmp #1000
bcc done
inx
cmp #10000
bcc done
inx
done txa
inc a
plx
rts
IntLength END
;
; Calculate the length of an AppleSoft file
;
;
; in: (stack) Ptr to the applesoft file
; out: (a:x) length of file
; (a = low word, x = hi word)
;
; {word word {bytes}* 0x00}*
;
; FYI, an applesoft file looks like:
; WORD - offset to next line, 0 if EOF
; WORD - line #
; variable # of bytes - if > $7f, is a token,
; byte 0 - eol
CalcLength START
_d equ 1
size equ 3
_rts equ 7
Ptr equ 9
pha
pha
phd
tsc
tcd
stz <size
stz <size+2
ldy #0
;
; ofset to next line, or 0 if done
;
m_loop lda [Ptr],y
bne *+5
brl done
iny
iny
;
; line #
;
lda [Ptr],y
jsr IntLength ;;calc size
clc
adc <size
sta <size
bcc foo
inc <size+2
foo iny
iny
s_loop lda [Ptr],y
iny
and #$00ff
beq next
cmp #$80
bcs _tok
;
; characters $01-$1f are special for bablefish, so must be ignored
; if in an applesoft file
;
cmp #$20
bcc s_loop
inc <size
bne s_loop
inc <size+2
bra s_loop
;
; add space for a carriage return
;
next anop ;;eol
inc <size
bne m_loop
inc <size+2
bra m_loop
;
; Calculate the size of the token from a look-up table
;
;
_tok anop
sec
sbc #$80
asl a ;; x2
asl a ;; x4
asl a ;; x8
tax
lda TOKENS,x ;;size of the token
clc
adc <size
sta <size
bcc s_loop
inc <size+2
bra s_loop
done anop
ldax <size
stax <Ptr
pld
ply
ply
ply
plax
phy
rts
END
;
; Convert file - detokenize a memory location into another memorry location
;
;
ConvertFile START
_d equ 1
_rts equ 3
Data equ 5
File equ 9
phd
tsc
tcd
ldy #0
;
; ofset to next line, or 0 if done
;
m_loop lda [File],y
bne *+5
brl done
iny
iny
;
; line #
;
phy ;;save
lda [File],y
pei Data+2
pei Data
jsr IntCvt
plx ;even up the stack
plx
ply ;;restore
lda [File],y
jsr IntLength
clc
adc <Data
sta <Data
bcc foo
inc <Data+2
foo iny
iny
s_loop lda [File],y
iny
and #$00ff
beq next
cmp #$80
bcs _tok
;
; characters $01-$1f are special for bablefish, so must be ignored
; if in an applesoft file
;
cmp #$20
bcc s_loop
;
; Character can be added as-is
;
short m
sta [Data]
long m
inc <Data
bne s_loop
inc <Data+2
bra s_loop
;
; add a carriage return
;
next anop ;;eol
short m
lda #$0D
sta [Data]
long m
inc <Data
bne m_loop
inc <Data+2
bra m_loop
;
; Add the size of the token from a look-up table
;
;
_tok anop
sec
sbc #$80
asl a ;; x2
asl a ;; x4
asl a ;; x8
tax
phy ;;save
lda TOKENS+6,x
pha
lda TOKENS+4,x ;;ptr to the token
pha
pei Data+2
pei Data
jsr CopyT
plx
plx
plx
plx
ply ;;restore
clc
adc <Data
sta <Data
bcc s_loop
inc <Data+2
bra s_loop
done anop
pld
ply ;;return address
pla
pla
pla
pla
phy
rts
END
;
; in A: the number
; stack: ptr to where to place it
;
; STACK UNCHANGED
IntCvt START
_d equ 1
_rts equ 3
Ptr equ 5
tay
phd
tsc
tcd
tya
pea $ffff ;;marker
;
; a = the number
;
l1 jsr div_10
pha ; remainder
tya
bne l1
ldy #0
lda #0
short m
l2 pla
bmi ex1 ;; found marker?
clc
adc #'0'
sta [Ptr],y
pla ;; s/b 0
iny
bra l2
ex1 pla ;;even up stack
lda #' '
sta [Ptr],y
long m
pld
rts
END
;entrance
; a = value to divide
;
;exit
; a = modulo
; y = quotient
div_10 START
ldy #0
div_loop anop
cmp #10
bcc done_div
; sec ; redundant!
sbc #10
iny
bra div_loop
done_div rts
END
;
; Copy a cstring from src->destination, NOT including the NULL char
;
CopyT START
_d equ 1
_rts equ 3
dest equ 5
src equ 9
phd
tsc
tcd
ldy #0
short m
loop lda [src],y
beq done
sta [dest],y
iny
bra loop
done anop
long m
tya
pld
rts
END
;
; Tack 4 0 bytes to the end of a ptr
; a = length of the ptr
; stack (4 bytes) = ptr itself.
Append0 START
_d equ 1
_rts equ 3
Ptr equ 5
tax ;;save
phd
tsc
tcd
txa ;;restore
clc
adc <Ptr
sta <Ptr
lda #0
adc <Ptr+2
sta <Ptr+2
lda #0
sta [Ptr]
ldy #2
sta [Ptr],y
pld
pla
plx
plx
pha
rts
END