home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CBM Funet Archive
/
cbm-funet-archive-2003.iso
/
cbm
/
c128
/
archivers
/
sda128.sda
/
SDA230.SDA
/
SDA.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-03-31
|
14KB
|
648 lines
;sda.asm (C)1987 - Ampere Metal
;====================================================================
;
cbm = 4032 ;64,128 or 4032
;
; kernel equates
;
.ifn cbm-4032 < ;if not PET
;
; C=64 C=128 PET (basic 4.0)
; ----- ----- -----
fnlen = $00b7 ; 00d1
la = $00b8 ; 00d2
sa = $00b9 ; 00d3
dv = $00ba ; 00d4
fnadr = $00bb ; 00da
status = $0090 ; 0096
open = $ffc0 ; F563
close = $ffc3 ; F2E2
l0 = $fa00 ;huffman code lengths ($7b00 for PET)
c0 = $fb00 ;huffman codes
c1 = $fc00 ;huffman codes
c2 = $fd00 ;huffman codes
g0 = $fe00 ;ascii for huffman code
>
chkin = $ffc6
chkout = $ffc9
clrchn = $ffcc
chrin = $ffcf
chrout = $ffd2
ibuf = $00fd ;indirect pointer into RAM
fn = $0100 ;where to put filename
;
.ife cbm-128 <
;
ndx = $00d0
keyd = $034a
basic = $4003
star = $1c01
>
.ife cbm-64 <
;
ndx = $00c6
keyd = $0277
basic = $e37b
star = $0801
>
.ife cbm-4032 <
;
status = $0096
fnlen = $00d1
fnadr = $00da
la = $00d2
sa = $00d3
dv = $00d4
open = $f563
close = $f2e2
ndx = $009e
keyd = $026f
basic = $b3ff
l0 = $7b00 ;huffman code lengths ($7b00 for PET)
c0 = $7c00 ;huffman codes
c1 = $7d00 ;huffman codes
c2 = $7e00 ;huffman codes
g0 = $7f00 ;ascii for huffman code
star = $0401
>
;
* = $0200
;
sqtyp *=*+1 ;0=store 1=pack 2=squeeze 3,5=crunch 4=squash
chkcrc *=*+2 ;checksum read from archive
len *=*+3 ;unsqueezed length in bytes (lo-high)
sqb *=*+2 ;squeezed length in 254 byte blocks
filtyp *=*+1 ;file type (p,s,u or r)
crc *=*+2 ;new calculated checksum
hcode *=*+3 ;huffman code
ncodsq *=*+1 ;number of huffman codes
tmp1 *=*+3 ;temp for hufin
tmp *=*+3 ;temp
ibit *=*+1 ;input bit
ibyt *=*+1 ;input byte
arcst *=*+1 ;eof flag
count *=*+1 ;run length coding count
crc2 *=*+1 ;temp
coff *=*+1 ;bit offset
prev *=*+1 ;rl char for output
clen *=*+1 ;hufman code length
prtflg *=*+1 ;flag output to screen or disk
bite *=*+1 ;bitin buffer
ltmp *=*+1
cmsk *=*+1
;
.wor star
* = star
;
.wor there, 10
.byt $9e
;
.ife cbm-64 <
.asc "(2063)", 0
>
.ife cbm-4032 <
.asc "(1039)", 0
>
.ife cbm-128 <
.asc "(7183)", 0
>
there .wor 0
;
main lda #<eof ;initialize buffer pointer
sta ibuf
lda #>eof
sta ibuf+1
lda #0 ;flag. 0=type this file, $ff=extract to disk
sta prtflg
;
main0 jsr get1st ;get archive entry header
bcs abor ;error reading header
bit prtflg ;first file?
bpl main1 ;yes..type it
jsr open ;otherwise open the disk file
bit status ;abort if device not present or disk error
bmi abor
ldx #8 ;and setup CHROUT
jsr chkout
main1 jsr getnxt ;unsqueeze a byte
bcs abor ;error with huffman code...abort
bit arcst ;input past end?
bmi main2 ;yes..next file
jsr chrout ;otherwise send to output
bit status
bmi abor
jmp main1 ;next byte
;
main2 jsr clrchn ;done with this file...close it
lda #8
jsr close
bit prtflg ;first file?
bmi main3 ;no
lda #0 ;yes...wait for key
sta ndx
wait lda ndx
beq wait
lda keyd
cmp #3 ;abort if RUN/STOP
beq abor
main3 lda #254
sta ibyt ;force bytin to get new block
sta prtflg ;and start sending to disk instead of screen
jsr bytin ;adjusts buffer pointer
lda chkcrc ;check if checksum is ok
cmp crc
bne crcerr
lda chkcrc+1
cmp crc+1
bne crcerr
lda #"o"
jsr chrout
lda #"k"
.byt $2c
crcerr lda #"?"
jsr chrout
jmp main0 ;next file
;
abor jsr clrchn ;exit...return to BASIC READY. prompt
lda #8
jsr close
jmp basic
;
;==============================================
; Read in archive header & initialize usq etc.
;==============================================
;
get1st ldx #16 ;zero a bunch of things
lda #0
g1st sta crc,x
dex
bpl g1st
lda #"0" ; 0: for filename
sta fn
lda #":"
sta fn+1
jsr bytin ;get version
cmp #2 ;must be 2
bne abor ;abort if version isn't 2
inx ;.x=0
newb1 jsr bytin ;get 1st part of header
sta sqtyp,x
inx
cpx #9
bne newb1
jsr bytin ;get fnlen
cmp #17 ;check for bad filename length
bcs abor ;its bad ... eof
tax ;save length
clc
adc #4
sta fnlen ;save length (+4 for 0: and ,type)
lda #13
jsr chrout
ldy #0
lda #<fn ;setup filename pointer for OPEN
sta fnadr
lda #>fn
sta fnadr+1
gth2 jsr bytin ;continue getting filename
sta fn+2,y
jsr chrout
iny
dex
bne gth2
lda #"," ;tag on ,type
sta fn+2,y
jsr chrout
iny
lda filtyp
sta fn+2,y
jsr chrout
lda #" "
jsr chrout
lda #8 ;open 8,8,1
tax
ldy #1 ;sa=1 for write
sta la
stx dv
sty sa
jsr bytin ;ignore record length
jsr bytin ;and date
jsr bytin
nou jsr chkhdr ;abort to BASIC if error in header
ldy sqtyp ;squeezed file?
cpy #2
beq dousq ;yes-get encoding table
cpy #4 ;squeezed+packed?
beq dousq ;yes-get encoding table
cpy #1 ;packed?
bne gth8 ;no stored or crunched
jsr bytin ;packed...ignore control character (always $fe)
gth8 clc ;got header...return
rts ;got header...return
;
dousq ldy #0 ;get huffman encoding table
tya
gth3 sta c0,y ;zero huffman codes and lengths
sta c1,y
sta c2,y
sta l0,y
iny
bne gth3
tax
gth6 lda #0
sta tmp1
sta tmp1+1
sta tmp1+2
ldy #5
gth4 jsr bitin ;get 5 bits (code length)
ror a
dey
bne gth4
ror a ;right justify
ror a
ror a
sta ltmp ;save code length
cmp #25 ;code length > 24?
bcs badcd ;yes...bad encoding table
cmp #0 ;length=0?
beq gth7 ;yes then no code to get
tay
gth5 jsr bitin ;else get Huffman code
rol tmp
rol tmp+1
rol tmp+2
dey
bne gth5
tay
gth9 ror tmp+2 ;justify it
ror tmp+1
ror tmp
rol tmp1
rol tmp1+1
rol tmp1+2
dey
bne gth9
jsr sert ;insert in table (sorted on code length)
gth7 inx
bne gth6 ;and repeat 256 times
dec ncodsq
clc
badcd rts ;got header
;
;---------------------
; verify header is ok
;---------------------
;
abort pla
pla
jmp abor ;bad header
;
chkhdr lda sqtyp ;must be 0,1,2 or 4
cmp #3 ;crunched?
beq abort ;yes-error
cmp #5 ;1 pass or bad header
bcs abort
lda filtyp ;must be p,s, or u
cmp #"p"
beq chok
cmp #"s"
beq chok
cmp #"u"
bne abort
chok rts
;
;----------------------------------------------------------------
; subroutine. add huffman code to table sorted by length of code
;----------------------------------------------------------------
;
sert stx srtx+1 ;save .x=ascii for this code
jsr ram ;all RAM
ldy #0
lda ltmp ;code length read from header
srt0 cpy ncodsq ;y=# of codes?
bne srt1 ;no-maybe insert it
srt00 sta l0,y ;else store it at end of table
lda tmp1 ;code
sta c0,y
lda tmp1+1
sta c1,y
lda tmp1+2
sta c2,y
inc ncodsq
srtx ldx #1
txa
sta g0,y ;save ascii
jmp rom ;re-enable ROMs
;
srt1 cmp l0,y
bcc srt2 ;new code is smaller. insert it
iny
bne srt0 ;always
;
srt2 sty srt3+1
ldy #$fe
srt4 jsr srt8
dey
srt3 cpy #0
bne srt4
jsr srt8
lda ltmp
jmp srt00
;
srt8 lda l0,y
sta l0+1,y
lda g0,y
sta g0+1,y
lda c0,y
sta c0+1,y
lda c1,y
sta c1+1,y
lda c2,y
sta c2+1,y
rts
;
;
.ife cbm-64 <
;
rom pha
rom0 lda #0 ;saved CR
sta $01
and #7 ;is I/O enabled?
beq nicl ;no...don't enable interrupts
pla
cli
rts
;
ram pha
lda $01 ;save CR
sta rom0+1
and #$f8 ;all RAM
sei ;kill interrupts
sta $01
nicl pla
rts
>
.ifn cbm-64 < ;if C-128 or PET
;
ram sta $ff01 ;bank 0 if 128, nothing if PET
rts
rom pha ;bank 15 if 128, nothing if PET
lda #$00
sta $ff00
pla
rts
>
;-----------------------------
; Unsqueeze a byte subroutine
;-----------------------------
;
; Use this routine to get one byte at a time from the archived file.
; The overflow flag, if set, indicates that there are no more bytes
; to get from this archive entry. The previous one was the last
; character of the squeezed file.
; The x and y registers are not affected by this routine
;
getnxt stx bast+1
sty basty+1
jsr dcln ;check for end of file
bit arcst
bmi bast0 ;eof...don't input past end
;
gxt ldx count ;on a run?
beq gnxt ;no
jsr rl33 ;yes - get repeated character
jmp usq89
;
gnxt ldx sqtyp ;what type of file?
beq usq88 ;stored..get byte
cpx #1
beq usq88 ;same if packed
jsr ram ;need to access tables at $fa00
jsr hufin ;else get huffman code
;
.ife cbm-64 <
;
pha ;re-enable ROMS
lda $01
ora #$07
sta $01
cli
pla
>
bcs bast ;error reading huffman code
bcc usq80
usq88 jsr bytin
usq80 cpx #0 ;was it stored?
beq usq89 ;yes then we've got a byte
cpx #2 ;was it squeezed?
beq usq89 ;yes then we've got a byte
jsr rlout ;otherwise it might need to be un-packed
usq89 jsr dcbo ;update checksum
bast0 clc
bast ldx #0
basty ldy #0
bit arcst
rts
;
;
dcln ldx len ;check for end of file
bne dl0
ldx len+1
bne dl1
ldx len+2
bne dl2
lda #$ff ;len is zero. flag eof
sta arcst
rts
;
dl2 dec len+2
dl1 dec len+1
dl0 dec len
rts
;
dcbo pha ;update checksum
inc crc2
eor crc2
clc
adc crc
sta crc
bcc dcbo1
inc crc+1
dcbo1 pla
rts
;
;----------------------------------
; run-length byte output for arc/x
;----------------------------------
;
rlout jmp rl1 ;changes
;
rl1 cmp #254 ;is it a control character?
beq contrl ;yes-get count,char
rts ;else send to output
;
contrl lda #<rl2 ;setup for count
sta rlout+1
lda #>rl2
sta rlout+2
gnx pla
pla
jmp gnxt
;
rl2 sta prev ;save count
lda #<rl3 ;and setup for char
sta rlout+1
lda #>rl3
sta rlout+2
jmp gnx
;
rl3 sty rl3y+1 ;save .y
ldy #<rl33
sty rlout+1
ldy #>rl33
sty rlout+2
ldy prev ;recall count
sty count
sta prev ;save char
rl33 dec count ;send char count times
beq rl3y ;last one. reset rlout
bne rl44
;
rl3y ldy #0
rl0 lda #<rl1 ;reset rlout
sta rlout+1
lda #>rl1
sta rlout+2
rl44 lda prev
rts
;
;----------------------------------------------
;read single byte from a file as a huffman code
;----------------------------------------------
;
hufin lda #0 ;reset length of code
sta clen
sta hfi1+1
sta coff
sta cmsk
inc cmsk
sta hcode
sta hcode+1
sta hcode+2
sty hfiy+1
stx hfix+1
hfilp jsr bitin ;get a bit
.ife cbm-128 <
sta $ff01
>
bcc zbit ;zero bit-just bump length
ldy coff ;else adjust code as well
lda cmsk
ora hcode,y
sta hcode,y
zbit asl cmsk ;adjust mask for next time
bcc zb2
rol cmsk
inc coff
zb2 inc clen ;check if code length >23
lda clen
cmp #24
bcc hfi1
nts sec ;code too long...bad file
jmp hfix
;
hfi1 ldy #0
hfi3 cmp l0,y ;check code length ok
beq hfi9 ;length the same check it
bcc hfilp ;less-get another bit
bcs nts ;length > ... must be an error
hfi9 ldx c0,y ;length ok. check if code is
cpx hcode
bne hfi2 ;no
ldx c1,y
cpx hcode+1
bne hfi2
ldx c2,y
cpx hcode+2
bne hfi2
lda g0,y ;got it
clc
hfix ldx #0
hfiy ldy #0
.ife cbm-128 <
jmp rom
>
rts
;
hfi2 iny ;try again for this length
beq nts ;error.. no code
sty hfi1+1
cpy ncodsq
bcc hfi3
beq hfi3
jmp nts ;none-error
;
;-------
; bitin
;-------
;
bits .byt 1, 2, 4, 8, 16, 32, 64, 128
;
bitin sty btiy+1
sta btia+1
ldy ibit ;offset into bit buffer
bne bti1 ;need a new byte if zero
jsr bytin
sta bite
bti1 lda bite ;put bit in carry
and bits,y
bne bti2
clc
.byt $24
bti2 sec
php
iny ;and adjust bit pointer for next time
cpy #8
bcc bti3
ldy #0
bti3 sty ibit
plp
btiy ldy #0
btia lda #0
rts
;
;-------
; bytin
;-------
;
bytin sty biy+1
jsr ram ;all RAM
ldy ibyt ;offset into file
cpy #254 ;end of buffer?
bcc bi1 ;no...just get byte
clc ;else bump buffer pointer
tya
adc ibuf
sta ibuf
bcc bi2
inc ibuf+1
bi2 ldy #0
bi1 lda (ibuf),y
iny
sty ibyt
biy ldy #0
jmp rom ;re-enable ROMs
;
.ife cbm-64 < ;pad file length to exactly 4 blocks
.asc "1234567890"
>
.ife cbm-128 <
.asc " (C) 1987 - Ampere Metal "
>
.ife cbm-4032 <
.asc " (C) 1987 - Ampere Metal "
>
eof = *
;
.end