Files
mips/_old/src/gunzip.log
T
jens 26291bca3d - initial import
git-svn-id: http://moon:8086/svn/mips@1 a8ebac50-d88d-4704-bea3-6648445a41b3
2014-07-20 15:01:37 +00:00

8801 lines
236 KiB
Plaintext

done
Not Last Block: Dynamic Huffman codes
12 table entries used
0x000 - link: 0x005 link: 0x001
0x001 - link: 0x002 link: 0x007
0x002 - link: 0x003 link: 0x004
0x003 - value: 0x000 value: 0x004
0x004 - value: 0x005 value: 0x006
0x005 - value: 0x007 link: 0x006
0x006 - value: 0x008 value: 0x009
0x007 - link: 0x008 link: 0x009
0x008 - value: 0x00a value: 0x00b
0x009 - value: 0x00c link: 0x00a
0x00a - value: 0x010 link: 0x00b
0x00b - value: 0x011 value: 0x012
115 table entries used
26 table entries used
Last Block: Dynamic Huffman codes
15 table entries used
0x000 - link: 0x00c link: 0x001
0x001 - link: 0x00a link: 0x002
0x002 - link: 0x008 link: 0x003
0x003 - link: 0x00e link: 0x004
0x004 - link: 0x007 link: 0x005
0x005 - value: 0x012 link: 0x006
0x006 - value: 0x000 value: 0x011
0x007 - value: 0x003 value: 0x00d
0x008 - value: 0x00c link: 0x009
0x009 - value: 0x004 value: 0x00b
0x00a - value: 0x00a link: 0x00b
0x00b - value: 0x005 value: 0x006
0x00c - value: 0x008 link: 0x00d
0x00d - value: 0x007 value: 0x009
0x00e - value: 0x00e value: 0x010
124 table entries used
29 table entries used
CRC: 5af05f03 5af05f03
Size: 00014623 00014623
; todo) detect zero-byte files/directories and skip
; DASM V2.12.04 source
; 1581 1541/71
; 02 can't find header block sector not found
; 03 no address mark detected no sync
; 04 data block not present data block not found
; 05 CRC error in data block data block checksum error
; 06 format error format error
; 07 verify error verify error
; 08 write to a write-protected disk write protect error
; 09 CRC error in header block header block checksum error
; 0a <reserved> data extends into next block
; 0b disk changed / disk ID mismatch disk ID mismatch / disk change
; 0c disk format not logical
; 0d floppy disk controller IC error
; 0e syntax error, invalid job number syntax error
; 0f no disk is present in the drive no drive present
; 8:05 D64.gz->file 1581->1581 unzip2.12
; gunzip.c64
; D64.gz 97275->174848
; 7:54 D64.gz->file 1581->1581 standard file I/O
; 9:00 D64.gz->file 1541->1581 standard file I/O
; 9:46 D64.gz->disk 1581->1541 custom sector write
; 10min D64.gz->disk 1541->1541 one drive custom read/write
; gunzip-std.c64
; D64.gz 97275->174848
; 4:24 D64.gz (skip) 1581->N/A standard file I/O + no save
; 8:10 D64.gz->file 1581->1581 standard I/O
; 13:30 D64.gz->disk 1581->1541 standard I/O (unzip128: 11 min unzip64: 13:10)
; 6:15 D64.gz->disk 1581->1570 burst I/O
; gunzip.128
; 1:22 D64.gz (skip) 1581->N/A standard I/O + burst read + no save
; 3:47 D64.gz->file 1581->1581 standard I/O + burst read
; 4:20 D64.gz->file 1581->1581 standard I/O
; 10:50 D64.gz->disk 1581->1541 standard I/O + burst read
; 11:25 D64.gz->disk 1581->1541 standard I/O
; 6:16 D64.gz->disk 1581->1570 burst read + burst write
; autoboot.zip->autoboot.prg 44sec (unzip101 took 1:17)
; tested on 1581, 1541-II and 1541 (aka "toaster")
processor 6502
ACPTR = $ffa5
CHKIN = $ffc6
CHKOUT = $ffc9
CHRIN = $ffcf
CHROUT = $ffd2
CIOUT = $ffa8
CLOSE = $ffc3
GETIN = $ffe4
CLALL = $ffe7
CLRCHN = $ffcc
LISTEN = $ffb1
OPEN = $ffc0
SECOND = $ff93
SETLFS = $ffba
SETNAM = $ffbd
TALK = $ffb4
TKSA = $ff96
UNLSN = $ffae
UNTLK = $ffab
;READST = $ffb7
ST = $90
#if MACH == 64 || MACH == 128
IDE64BlockWrite = $DEF1
IDE64BlockRead = $DEF4
IDE64BR = $6e ;$6e $6f
be = $69 ;dc.b 0
#endif
#if MACH != 20
D2PRA = $DD00 ; c128 SERIAL PORT LOCATION
CLKOUT = $10 ; SLOW SERIAL CLOCK OUTPUT BIT MASK
CLKIN = $40 ; SLOW SERIAL CLOCK INPUT BIT MASK
D1ICR = $DC0D ; 6526 cia INTERRUPT CONTROL REGISTER
D1SDR = $DC0C ; 6526 cia SERIAL DATA REGISTER
#endif
;MACH = 64
;CUSTOM = 1 ; custom sector write (~11s/track) instead of U2 (~18s/track)
; + custom read w/ custom write
; =============================== C64 =====================================
#if MACH == 64
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $3100
crc32_tab1 = $3200
crc32_tab2 = $3300
crc32_tab3 = $3400
; $cf00-cfff reserved for REU/ramdos
inBuf = $3000
PROGEND = $3000
buf32k = $3500 ; $3500-$cf00 bytes for the output/history buffer
bufsz = $9a00 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
; We would need $ab00 bytes for 4-pass D64, $8900 for 5 passes
curplace EQU $14 ; $15
bb EQU $2 ; bit bucket
bTmp EQU $f7 ; temporary pointer for functions
; equ $f8
zp0 EQU $f9
zp1 equ $fa
countLo EQU $fb
countHi EQU $fc
offset EQU $fd
; EQU $fe
lengths EQU $9e ; for huffman table creation
; EQU $9f
store EQU $ff ; temporary storage
; Used ZP locations: $02, $14-$15, $6a-$6f, $9e-$9f, $f7-$ff and $69 if in c64/128
FASTSER = $02a3
ORG $0801
DC.B $0b,8,$ef,0 ; '239 SYS2061'
DC.B $9e,$32,$30,$36
DC.B $31,0,0,0
#endif
; =============================== C128 ====================================
#if MACH == 128
; $0b00 Cassette buffer
; $0c00 RS232 Input Buffer
; $0d00 RS232 Output Buffer
; $0e00 System Sprites
; $0f00 System Sprites
; $1300-$17ff unused
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $0b00
crc32_tab1 = $0c00
crc32_tab2 = $0d00
crc32_tab3 = $0e00
inBuf = $0f00
;bitReverse = $0d00
PROGEND = $3e00
buf32k = $3e00 ; $3e00-$c000
bufsz = $8200 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
; We would need $ab00 bytes for 4-pass D64, $8900 for 5 passes
S = $1300
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
curplace EQU $86 ; $87
bb EQU $8c ; bit bucket
countLo EQU $88
countHi EQU $89
lengths EQU $8a ; for huffman table creation
; EQU $8b
bTmp EQU $fa ; temporary pointer for functions
; equ $fb
zp0 EQU $fc
zp1 equ $fd
offset EQU $fe
; EQU $ff
store EQU $8d ; temporary storage
prns = $ff7d
SETBANK = $ff68
SPIN_OUT = $FF47 ; sET UP FAST SERIAL FOR INPUT OR OUTPUT.
; sec FOR OUTPUT, clc FOR INPUT.
READBANK = $ff74 ; lda (ZP),y bank in X, ZP in A
WRITEBANK = $ff77 ; sta (ZP),y bank in X, value in A, ZP in $02b9
VERIFYBANK = $ff7a ; cmp (ZP),y bank in X, value in A, ZP in $02c8
FASTSER = $0a1c
ORG $1c01
DC.B $0b,$1c,$ef,0 ; '239 SYS7181'
DC.B $9e,$37,$31,$38
DC.B $31,0,0,0
lda $ff00
pha
lda #$0e ; RAM0, System ROM, RAM, BASIC
sta $ff00
lda #0
sta $f7 ; enable SHIFT-C=
sta $f8
sta $f9
tax
jsr SETBANK ; I/O source/destination RAM0 64k
#endif
; =============================== VIC20 ====================================
#if MACH == 20
; $1201-2000 base memory
; $2000-3fff 8k expansion
; $4000-5fff 8k expansion
; ----
; $6000-7fff 8k expansion
; ----
; $a000-bfff 8k expansion
; $0400-0fff 3k expansion
bitReverse = $2600
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $2700
crc32_tab1 = $2800
crc32_tab2 = $2900
crc32_tab3 = $2a00
inBuf = $2b00
PROGEND = $2600
buf32k = $3000
bufsz = $3000
S = $2c00 ; $2c00..$2fff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
curplace EQU $86 ; $87
bb EQU $8c ; bit bucket
countLo EQU $88
countHi EQU $89
lengths EQU $8a ; for huffman table creation
; EQU $8b
bTmp EQU $fa ; temporary pointer for functions
; equ $fb
zp0 EQU $fc
zp1 equ $fd
offset EQU $fe
; EQU $ff
store EQU $8d ; temporary storage
ORG $1201
DC.B $0b,8,$ef,0 ; '239 SYS4621'
DC.B $9e,$34,$36,$32
DC.B $31,0,0,0
#endif
; =============================== Plus/4 ====================================
#if MACH == 4
; C16 $1000-$3fff +/4 $1000-$fd00
CRC = $d8 ; 8,9,a,b
crc32_tab0 = $3000
crc32_tab1 = $3100
crc32_tab2 = $3200
crc32_tab3 = $3300
inBuf = $3800
PROGEND = $3000
buf32k = $3900 ; $3900..$fd00
bufsz = $c400
S = $3400 ; $3400..$37ff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
; $00D8-00E8 216-232 Area for use by application software
curplace EQU $dc ; $dd
bb EQU $de ; bit bucket
countLo EQU $df
countHi EQU $e0
lengths EQU $e1 ; for huffman table creation
; EQU $e2
bTmp EQU $e3 ; temporary pointer for functions
; equ $e4
zp0 EQU $e5
zp1 equ $e6
offset EQU $e7
; EQU $e8
store EQU $d7 ; temporary storage
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; =============================== C16 ====================================
#if MACH == 16
; C16 $1000-$3fff +/4 $1000-$fd00
bitReverse = $2600
CRC = $d8 ; 8,9,a,b
crc32_tab0 = $2700
crc32_tab1 = $2800
crc32_tab2 = $2900
crc32_tab3 = $2a00
PROGEND = $2600
inBuf = $2b00
buf32k = $3000 ; $3000..$8000
bufsz = $5000 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
S = $2c00 ; $2c00..$2fff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
; $00D8-00E8 216-232 Area for use by application software
curplace EQU $dc ; $dd
bb EQU $de ; bit bucket
countLo EQU $df
countHi EQU $e0
lengths EQU $e1 ; for huffman table creation
; EQU $e2
bTmp EQU $e3 ; temporary pointer for functions
; equ $e4
zp0 EQU $e5
zp1 equ $e6
offset EQU $e7
; EQU $e8
store EQU $d7 ; temporary storage
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; ========================================================================
cli ; in case..!?!?
jsr prns
dc.b 147
#if MACH == 64
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$b0,$ae,$b0,$ae,$ae,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$20,$ab,$ae,$ad,$b3
#endif
#if MACH == 4
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$20,$ae,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7b,$ad,$b3
#endif
#if MACH == 128
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$ae,$b0,$ae,$b0,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$b0,$bd,$ab,$b3
#endif
#if CUSTOM
dc.b "V1.11CUSTOM 19.11.2002",13
#else
dc.b "V1.11 19.11.2002",13
#endif
#if MACH == 64
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$bd,$ad,$bd,$20,$bd
#endif
#if MACH == 4
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$20,$20,$bd
#endif
#if MACH == 128
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$ad,$bd,$ad,$bd
#endif
dc.b " BY PASI'ALBERT'OJALA", 13
dc.b " HTTP://WWW.CS.TUT.FI/%7EALBERT/", 13, 13, 0
#if MACH != 20 && MACH != 16
ldx #0 ; create the CRC32 table (makecrc.c)
crc$ lda #0
sta CRC+3
sta CRC+2
sta CRC+1
stx CRC+0
ldy #8
1$ lsr CRC+3
ror CRC+2
ror CRC+1
ror CRC+0
bcc 0$
lda #$ed
eor CRC+3
sta CRC+3
lda #$b8
eor CRC+2
sta CRC+2
lda #$83
eor CRC+1
sta CRC+1
lda #$20
eor CRC+0
sta CRC+0
0$ dey
bne 1$
lda CRC+0
sta crc32_tab0,x
lda CRC+1
sta crc32_tab1,x
lda CRC+2
sta crc32_tab2,x
lda CRC+3
sta crc32_tab3,x
inx
bne crc$
#else
jsr vic20init
#endif /* V20 */
#if MACH == 64 || MACH == 128
jsr CheckIDE64
#endif
restart lda #0
#if MACH == 64 || MACH == 128
sta inTrack
;sta inSector
sta d64mode
sta first
#endif
sta gzip
idrive$ jsr prns
dc.b "INPUT", 0
lda #14 ; channel #
jsr askdrive
beq idrive$
sta inDrive
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda inDrive
ldx #14
jsr CheckBurst
sta inBurst
#endif
#endif
rfile$ jsr prns
dc.b "INPUT FILE?", 13, 34, 0
lda #0
sta inFile
lda #<inFile
ldx #>inFile
ldy #28 ; max filename length
jsr getstr
lda #0
sta inFile,y
sty inLen
lda #34
jsr OK_KEY
#if MACH != 20 && MACH != 16
jsr ReadDir
lda inLen
beq rfile$
;lda inTrack ; allow non-existing files
;beq rfile$
#endif /* V20 */
odrive$ jsr prns
dc.b "OUTPUT", 0
lda #15
jsr askdrive
beq odrive$
sta outDrive
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda outDrive
ldx #15
jsr CheckBurst
sta outBurst
#endif
#endif
#if CUSTOM == 1
lda outDrive
cmp inDrive
bne oneortwo$
lda fdos
cmp #"A"
bne oneortwo$ ; not a 1541-format disk
lda inTrack
beq oneortwo$ ; we did not find the file from the directory
jsr prns
dc.b "DISSOLVE D64 TO 1541/71 DRIVE ",18,"Y",146,"/",18,"N",146," ? ", 0
onedrive$
jsr getkey
cmp #"N"
beq oneortwo0$
cmp #"Y"
bne onedrive$
jsr OK_KEY
; okay, one drive and D64, set d64mode = $84
lda #$84
sta d64mode ; one-drive mode: custom read and write
jsr initwriter
jmp 2$
oneortwo0$
jsr OK_KEY
; Open input file
oneortwo$
lda #0
sta inMode
#endif
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda inBurst
beq openin$ ; can't use burst read -> use sequential read
lda inTrack
bne 2$ ; start t&s known, use burst read
#endif
#endif
openin$ ldx #<inFile
ldy #>inFile
lda inLen
jsr SETNAM
lda #2
ldx inDrive
ldy #0 ; open 2,8,0,"fileName"
jsr SETLFS
jsr OPEN
#if MACH == 64 || MACH == 128
inc inMode
#endif /* V20 */
ldx #14
jsr geterror
cmp #0
beq 2$
jsr CLALL
jsr CLRCHN
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
jsr CR
jmp restart
2$ ldy #0
sty be
sty mode
sty overwritemode
#if MACH == 64
lda #$36 ; turn off BASIC ROM for good..
sta 1
#endif
again: jsr InitBuffer32k
jsr BYTEALIGN
jsr Get2Bytes
sty flags+0
sta flags+1
cpy #$1f
beq ok1$
cpy #$50
bne mismatch2$
cmp #$4b
bne mismatch3$
jsr Get2Bytes
cpy #$30
bne no0$
cmp #$30
beq again ; skip "PK00"
no0$
cpy #$01 ; end of Zip central directory ($50 $4b $05 $06)
bne no1$
cmp #$02
beq central$
no1$
cpy #$03
bne mismatch3$
cmp #$04
bne mismatch3$
; Zip local file header $50 $4b $03 $04
#if MACH != 20 && MACH != 16
inc first ; got ID
#endif /* V20 */
jmp ZipHeader
central$:
jsr prns
dc.b "ZIP CENTRAL DIRECTORY REACHED", 13, 0
jmp err ; Zip central directory ($50 $4b $03 $04)
; end there
mismatch2$:
#if MACH != 20 && MACH != 16
lda first
bne mismatch3$
jmp checkD64
#endif /* V20 */
mismatch3$:
jmp mismatch
ok1$ cmp #$8b ; $1f $8b == GZIP ID
bne mismatch2$
#if MACH != 20 && MACH != 16
inc first ; got ID
#endif /* V20 */
inc gzip ; it's a gzip file (ID = $1f8b)
jsr GetByte ; Compression method
cmp #8
beq ok3$
pha
jsr CLRCHN
pla
jsr puthex
jmp nomethod
ok3$ jsr GetByte ; Flags
sta flags
and #$e0
beq ok4$
jsr prns
dc.b "UKNOWN FLAGS!", 13, 0
ok4$ jsr Get2Bytes ; Skip modification time (4 bytes)
jsr Get2Bytes
jsr Get2Bytes ; Skip extra flags and os (1 + 1 bytes)
; byte 10
lda flags
and #4
beq 1$
; Skip extra field (3..32770 bytes)
jsr Get2Bytes
sty countLo
sta countHi
2$ jsr GetByte
dec countLo
bne 2$
dec countHi
bpl 2$
1$ ldy #0 ; filename character counter
lda flags
and #8
beq 3$
; Skip filename (NUL-terminated)
4$ jsr GetByte
cmp #"/"
bne nopath$
path$ ldy #0 ; discard paths
beq 4$
nopath$ cmp #":"
beq path$ ; discard paths
cmp #$60
bcc ok$
and #$5f ; make it "lowercase"
;ora #$80 ; "uppercase" it
ok$ sta fileName,y
iny
cmp #0
bne 4$
dey
3$ sty fileLen
lda flags
and #16
beq 5$ ; Skip comment (NUL-terminated)
6$ jsr GetByte
tay ;cmp #0
bne 6$
5$ lda flags
and #2
beq 7$ ; Skip CRC16
jsr Get2Bytes
7$
lda #0
ldy #3
clr0$ sta compSize,y ; compressed size
sta uncSize,y ; uncompressed input size
dey
bpl clr0$
HandleFile:
#if CUSTOM == 1
lda d64mode
bmi d64s$ ; if in one-drive D64 mode, do not destroy the mode
#endif
#if MACH != 20 && MACH != 16
lda #0
sta d64mode
d64s$
#endif /* V20 */
jsr PrintFileName
#if CUSTOM == 1
lda d64mode
bpl chk2$
jsr CR
jmp 11$
#endif
chk2$ lda fileLen
bne cc0$
jmp skipit$
cc0$ lda mode
cmp #"A"
bne check$
lda #15
sec
sbc fileLen
tay
space$ lda #" "
jsr CHROUT
dey
bpl space$ ; at least one space is printed
jmp modeok2$
; Check what the user wants to do with this!
check$ ldy fileLen
bne ask$
jmp skipit$ ; no filename (directory), skip it
ask$ jsr prns
dc.b " ",18,"Y",146,"ES ",18,"N",146,"O ",18,"A",146,"LL ",18,"E",146,"DIT ", 0
#if MACH != 20 && MACH != 16
lda inDrive
cmp outDrive
bne diff$
; same drive
lda #0 ; mask away D,8
sta cmpd$+1
#endif /* V20 */
jsr prns
dc.b "? ", 0
jmp dagain$
edit$ jsr OK_KEY
lda #34
jsr CHROUT
lda #<fileName
ldx #>fileName
ldy #38 ; max filename length
jsr getstr
lda #0
sta fileName,y ; zero-terminate it again
sty fileLen
lda #34
jsr CHROUT
jmp check$ ; to the top!
diff$
#if MACH != 20 && MACH != 16
lda #$ff ; enable D,8
sta cmpd$+1
jsr prns
#if CUSTOM == 0
dc.b "D",18,"8",146,"1 "
#endif
dc.b 18,"D",146,"64 ? ", 0
#endif
dagain$ jsr getkey
sta mode
cmp #"Y"
beq modeok$
cmp #"N"
beq modeok$
cmp #"A"
beq modeok$
cmp #"E"
beq edit$
cmp #3
beq break$ ; handle ^C
; TODO: change target drive
#if MACH != 20 && MACH != 16
cmpd$ and #$ff
cmp #"D"
beq d64$
#if CUSTOM == 0
cmp #"8"
beq d81$
bne dagain$
d81$ lda #8
dc.b $2c ; bit $nnnn
#else
bne dagain$
#endif
d64$ lda #4
sta d64mode
ldx #1
stx oTrack
dex
stx oSector
#else
jmp dagain$
#endif /* V20 */
; fall through!
modeok$ jsr CLRCHN
lda mode
jsr OK_KEY
modeok2$
lda mode
cmp #"N" ; skip it
bne do$
skipit$ jsr prns
dc.b " SKIPPING..",13, 0
jmp 11$
break$ jsr CLALL
jsr CLRCHN
jsr CR
jmp restart
do$
#if MACH != 20 && MACH != 16
lda d64mode
beq file$ ; filemode
; =================================
#if CUSTOM
jsr initwriter
jmp 11$
; =================================
#else
#if MACH == 64 || MACH == 128
lda outBurst
bne 11$ ; can perform burst write -> do not open file
#endif
ldx #<d64chan
ldy #>d64chan
lda #1
jsr SETNAM
lda #3
ldx outDrive
tay ;ldy #3 ; open 3,8,3,"#"
jsr SETLFS
jsr OPEN
ldx #15
jsr geterror
cmp #0
bne err1$
lda #"3"
jsr initbp
ldx #15
jsr geterror
cmp #0
beq 11$
err1$ jmp diskerror
#endif
#endif /* V20 */
file$ ; Open output file
ldx #<fileName
ldy #>fileName
lda fileLen
bne 10$
ldx #<fileDef
ldy #>fileDef
lda #6 ; 'stdout'
10$ jsr SETNAM
lda #3
ldx outDrive
ldy #1 ; open 3,8,1,"fileName"
jsr SETLFS
jsr OPEN
ldx #15
jsr geterror
cmp #0
beq noerr4$
pha
lda #3
jsr CLOSE
jsr CLRCHN
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
pla
cmp #63 ; check "FILE EXISTS" and ask for overwrite?
bne ovback$
jsr overwrite
beq file$ ; did scratch the file, try opening again
ovback$ jmp check$
noerr4$
11$ ldx #3
loop11$ lda #0
sta outSize,x
lda #255
sta CRC,x
dex
bpl loop11$
lda gzip
bne DeLoop
lda method+0
beq stored$
cmp #8
beq DeLoop ; method 8
#if MACH != 20 && MACH != 16
cmp #1 ; shrink
bne noshr$
jsr Shrink
jmp DeOut
noshr$ cmp #6
bne noimp$
jsr Implode
lda ferr
beq impok$
jmp invalid ; invalid huffman tree
impok$ jmp DeOut
noimp$
jsr Reduce
jmp DeOut
#endif /* V20 */
stored$ jsr ZipStored
jmp DeOut
; End of header - check the block type and do it.
DeLoop ldx #1
jsr GetBits
sta last$+1
ldx #2
jsr GetBits
cmp #1 ; 0-1 -> CC
beq 10$
bcs 9$
jsr Stored ; 0 == 0
jmp last$
9$ jsr prns
dc.b "FIXHUF ", 0
jsr Fixed ; 1 == 2 (bits not reversed)
jmp last$
10$ jsr prns
dc.b "DYNHUF ", 0
jsr Dynamic ; 2 == 1 (bits not reversed)
lda ferr
bne cont3
last$ lda #0
beq DeLoop ; Until last block
DeOut jsr BYTEALIGN
lda gzip
bne cont1$ ; GZip - always has the record
lda flags+0
and #8
beq cont3 ; Zip - does not have the record
lda #<uncCRC ; get the descriptor
ldy #>uncCRC
jsr getcrc
lda uncCRC+0
cmp #$50
bne cont3$
lda uncCRC+1
cmp #$4b
bne cont3$
lda uncCRC+2
cmp #$07
bne cont3$
lda uncCRC+3
cmp #$08
bne cont3$
cont1$
lda #<uncCRC
ldy #>uncCRC
jsr getcrc
cont3$ lda gzip
bne cont2$ ; GZip - does not have the record
lda #<compSize
ldy #>compSize
jsr getcrc
cont2$
lda #<uncSize
ldy #>uncSize
jsr getcrc
cont3 jsr FlushBuffer
jsr InitBuffer32k
lda mode
cmp #"N" ; skip it
beq file2$ ; did not open an output file
#if MACH != 20 && MACH != 16
lda d64mode
beq file$ ; filemode
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda outBurst
bne i0$ ; can perform burst write -> did not open file
#endif
lda #3
jsr CLOSE
#endif
i0$ ldx #15
jsr I0
jmp file2$
file$
#endif /* V20 */
lda #3
jsr CLOSE
file2$ lda ferr
bne invalid
jsr prns
dc.b "SIZE ", 0
lda #<outSize
ldy #>outSize
jsr showsize
ldy #3
chk$ lda outSize,y
cmp uncSize,y
bne sizemismatch
dey
bpl chk$
jsr CR
ldx #3
chkc$ lda CRC+0,x
eor #255
sta CRC+0,x
cmp uncCRC+0,x
bne crcmismatch
dex
bpl chkc$
jmp again
sizemismatch:
jsr prns
dc.b " WRONG ", 0
lda #<uncSize
ldy #>uncSize
jsr showsize
jsr CR
jmp again
crcmismatch:
jsr prns
dc.b "CRC WRONG ", 0
lda #<CRC
ldy #>CRC
jsr showsize
lda #" "
jsr CHROUT
lda #<uncCRC
ldy #>uncCRC
jsr showsize
jsr CR
jmp again
invalid: ; invalid huffman tree etc.
jsr prns
dc.b "CORRUPT HUFFMAN TREE", 13, 0
jmp err
mismatch: ; magic number not $1f8b or compression method != 8
jsr prns
dc.b "ID MISMATCH OR END OF FILE", 13, 0
jmp err
diskerror:
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
jsr CR
err
#if MACH != 20 && MACH != 16
lda d64mode
bmi d64$
#if MACH == 64 || MACH == 128
lda inMode
beq d64$ ; did not open the file -- used custom read
#endif
#endif /* V20 */
lda #2
jsr CLOSE ; close the input file
d64$ jsr CLALL
jsr CLRCHN
#if MACH == 64
lda #$37
sta 1
#endif
#if MACH == 128
pla
sta $ff00 ; restore memory config
#endif
cli ; just in case
rts
getcrc: sta str$+1
sty str$+2
ldy #0
crc0$ jsr GetByte
str$ sta $aaaa,y
iny
cpy #4
bne crc0$
rts
overwrite
lda overwritemode
cmp #"A"
beq scratch$
jsr prns
dc.b "OVERWRITE? ", 18,"Y",146,"ES ",18,"N",146,"O ",18,"A",146,"LL ", 0
ow1$ jsr getkey
cmp #"N"
beq no$
cmp #"Y"
beq y$
cmp #"A"
bne ow1$
sta overwritemode ; overwrite all
y$ jsr OK_KEY
scratch$
ldx #15
jsr CHKOUT
lda #"S"
jsr CHROUT
lda #"0"
jsr CHROUT
lda #":"
jsr CHROUT
ldy #0
ow2$ lda ($bb),y
jsr CHROUT
iny
cpy $b7
bne ow2$
jsr CLRCHN
ldx #15
jsr geterror
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
yes$ lda #0
rts
no$ lda #1
rts
ZipHeader:
jsr Get2Bytes ; version needed to extract
jsr Get2Bytes
sty flags+0
sta flags+1 ; general purpose bit flags
; If bit 3 is set, data descriptor follows data
jsr Get2Bytes
sty method+0
sta method+1 ; compression method
; 0 - stored
; 8 - Deflate
jsr Get2Bytes ; last mod file time
jsr Get2Bytes ; last mod file date
lda #<uncCRC
ldy #>uncCRC
jsr getcrc
lda #<compSize
ldy #>compSize
jsr getcrc
lda #<uncSize
ldy #>uncSize
jsr getcrc
jsr Get2Bytes
sty zfileLen+0
sta zfileLen+1
jsr Get2Bytes
sty zextraLen+0
sta zextraLen+1
ldy #0
inc zfileLen+0
inc zfileLen+1
jmp zc0$
zl0$ jsr GetByte
cmp #"/"
bne nopath$
path$ ldy #0 ; discard paths
beq zc0$
nopath$ cmp #":"
beq path$ ; discard paths
cmp #$60
bcc ok$
and #$5f ; make it "lowercase"
;ora #$80 ; "uppercase" it
ok$ sta fileName,y
iny
zc0$ dec zfileLen+0
bne zl0$
dec zfileLen+1
bne zl0$
lda #0
sta fileName,y ; zero-terminate
sty fileLen
inc zextraLen+0
inc zextraLen+1
jmp zc1$
zl1$ jsr GetByte
zc1$ dec zextraLen+0
bne zl1$
dec zextraLen+1
bne zl1$
lda method+1
bne nome$
lda method+0
beq stored$
cmp #8
#if MACH != 20 && MACH != 16
beq deflate$
cmp #1
beq shrink$
cmp #7
bcs nome$ ; 2..5, 6 ok
shrink$
implode$
deflate$
#else
bne nome$
#endif
stored$ jmp HandleFile
nome$
jsr PrintFileName
;lda method+1
;jsr puthex
lda method+0
jsr puthex
lda flags+0
and #8
bne nomethod ; Zip - does have the record -> size not valid
; just skip the unknown part..
jsr prns
dc.b ": UNKNOWN METHOD - SKIP", 13, 0
ldx #3
2$ inc compSize,x
dex
bpl 2$
jmp 1$
0$ jsr GetByte
1$ dec compSize+0
bne 0$
dec compSize+1
bne 0$
dec compSize+2
bne 0$
dec compSize+3
bne 0$
jmp DeOut
; TODO: skip until the next ZIP file header
nomethod:
jsr prns
dc.b ": UNKNOWN METHOD", 13, 0
jmp err
PrintFileName:
jsr CLRCHN
lda #34
jsr CHROUT ; "
ldx #<fileName
lda #>fileName
ldy fileLen
jsr putstr
lda #34
jmp CHROUT
Stored jsr BYTEALIGN
jsr Get2Bytes
sty compSize+0
sta compSize+1
lda #0
sta compSize+2
sta compSize+3
jsr GetByte
eor #255
eor compSize+0
beq 1$
jmp err
1$ jsr GetByte
eor #255
eor compSize+1
beq 2$
jmp err
2$ ;jmp ZipStored
ZipStored:
jsr prns
dc.b "STORED ", 0
ldx #3
loop$ inc compSize,x
dex
bpl loop$
bmi 1$
0$ jsr GetByte
jsr PutBuffer
1$ dec compSize+0
bne 0$
dec compSize+1
bne 0$
dec compSize+2
bne 0$
dec compSize+3
bne 0$
rts
Get2Bytes:
jsr GetByte
tay
jmp GetByte
; Out Input pattern Input
; 256 0000000 0
; : : :
; 279 0010111 23
; 0 00110000 48
; : : :
; 143 10111111 191
; 280 11000000 192
; : : :
; 287 11000111 199
; 144 110010000 400
; : : :
; 255 111111111 511
; Note the bit order!
; Fixed Huffman decode -- 59 bytes (UnZip: 98 bytes)
Fixed ldx #7
jsr GetBits ; Reverse default bit order
cmp #24
bcc 023$
; 24..127
jsr GetBit
rol ; 48..255
cmp #200
bcc 48199$
; 200..255
;sec
sbc #128 ; 72..127
jsr GetBit
rol ; 144..255
0$ jsr PutBuffer ; 0..143 & 144..255
jmp Fixed ; continue loop
48199$ ;clc ; 48..199
sbc #47 ; 0..151
cmp #144
bcc 0$
; 144..151
;sec
adc #135 ; 280..287 (24..31)
bcs lz77$
023$ cmp #0 ; 0..23 -> 256..279
bne lz77$
rts ; 256 == EOF
lz77$ jsr GetLen ; 1..23
ldx #5
jsr GetBits ; reverse default bit order
jsr CopyLz
jmp Fixed
GetLen tay ; j
;dey ; 1..23 -> 0..22
sty store
ldx cplext-1,y
jsr READBITS ; 0..5 bits
;clc
adc #3 ; does not overflow
ldy store
adc cplens_3-1,y ; 0..255 may overflow
sta countLo
lda #0
rol ;adc #0
sta countHi
rts
; cpdist-index in A
; offset in "offset"
; length in countLo & countHi
CopyLz sta store
tay
ldx cpdext,y
cpx #9
bcs 913$
jsr READBITS ; 1..8 bits
sta offset+0
lda #0
jmp ov$
913$ stx x$+1
ldx #8 ; 9..13 bits
jsr READBITS
sta offset+0
x$ lda #9
and #7
tax
jsr READBITS
ov$ sta offset+1
ldy store
lda cpdistLo,y
;clc ; READBITS cleared it (either one)
adc offset+0
sta offset+0
lda cpdistHi,y
adc offset+1
sta offset+1
; Entry-point for Implode/Reduce
CopyLz2 lda outCmd+1 ; low-byte of current output position
sec
sbc offset+0
sta offset+0
lda outCmd+2 ; high-byte of current output position
sbc offset+1
bcc buffix$ ; wrapped below 0, must be out of buffer -> fix
cmp #>buf32k
bcs bufok$ ; not below 0 and not below buffer start -> ok
; not below 0 but below buffer start -> fix
buffix$ ;clc ; C is clear in both entries
adc #>bufsz
bufok$ sta offset+1
; change dec;lda;cmp #255;bne -> dec;bne
inc countLo
inc countHi
jmp l3$
l0$
ldy #0
lda (offset),y
jsr PutBuffer
inc offset+0
bne l3$
ldy offset+1
iny
cpy #>(buf32k+bufsz) ; wrap to the start of the (ring)buffer
bne l2$
ldy #>buf32k
l2$ sty offset+1
l3$ dec countLo
bne l0$
dec countHi
bne l0$
rts
Dynamic ldx #5
jsr READBITS
;clc
adc #1
sta literalCodes+0 ; + 257
lda #1
sta literalCodes+1
ldx #5
jsr READBITS
;clc
adc #1
sta distCodes ; + 1
ldx #4
jsr READBITS
;clc
adc #4
sta countLo
lda #0
sta countHi
;lda #0
ldx #19
0$ sta codelens,x
dex
bpl 0$
1$ ldx #3
jsr READBITS
ldy countHi
ldx border,y
sta codelens,x
inc countHi
dec countLo
bne 1$
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<distanceTree
sta Places+0
lda #>distanceTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy #0
lda #19
jsr CreateTree
beq tok1$
; invalid tree
rts
;
tok1$ lda literalCodes+0
clc
adc distCodes
sta countLo
lda literalCodes+1
adc #0
sta countHi
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
5$ lda #<distanceTree ; bitlen decode 117 bytes (UnZip 173 bytes)
ldy #>distanceTree
jsr DecodeValue
cmp #16
beq 16$
bcc 015$
; j>16
cmp #17
beq 17$
ldx #7
jsr READBITS
;clc
adc #11
jmp 8$
17$ ldx #3
jsr READBITS
;clc
adc #3
8$ tax
ldy #0
tya ;lda #0
9$ sta (lengths),y
inc lengths+0
bne l0$
inc lengths+1
l0$ dec countLo
bne l1$
dec countHi
l1$ dex
bne 9$
jmp 6$
16$ ; j==16
ldx #2
jsr READBITS
;clc
adc #3
tax
dec lengths+1
ldy #255
7$ lda (lengths),y ; lengths[i-1]
inc lengths+0
bne l2$
inc lengths+1
l2$ sta (lengths),y ; lengths[i]
dec countLo
bne l3$
dec countHi
l3$ dex
bne 7$
inc lengths+1
jmp 6$
015$ ; j<16
ldy #0
sta (lengths),y
inc lengths+0
bne l4$
inc lengths+1
l4$ dec countLo
bne 6$
dec countHi
6$ lda countHi
bpl 5$
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<literalTree
sta Places+0
lda #>literalTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy literalCodes+1
lda literalCodes+0
jsr CreateTree
beq tok2$
; invalid tree
rts
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
tok2$ lda #<distanceTree
sta Places+0
lda #>distanceTree
sta Places+1
lda #<codelens
clc
adc literalCodes+0
sta lengths+0
lda #>codelens
adc literalCodes+1
sta lengths+1
ldy #0
lda distCodes
jsr CreateTree
beq loop
; invalid tree
rts
literal jsr PutBuffer
loop lda #<literalTree
ldy #>literalTree
jsr DecodeValue
bcc literal
;cmp #0
beq eof$
jsr GetLen
lda #<distanceTree
ldy #>distanceTree
jsr DecodeValue
; cpdist-index in A
; pre-offset in "offset"
; length in countLo & countHi
jsr CopyLz
jmp loop
eof$ rts
#if MACH != 20 && MACH != 16
;--------------- D64 -> DISK ------------------------
mismatch3:
jmp mismatch
checkD64: ; Is it uncompressed D64?
lda d64mode
bmi mismatch3 ; one-drive D64 mode selected -> can't be
lda fdos
cmp #"A"
beq mismatch3 ; a 1541-format disk -> can't be
jsr prns
dc.b "IS THIS A NON-COMPRESSED D64? ", 18,"Y",146,"ES ",18,"N",146,"O ", 0
again$ jsr getkey
cmp #"N"
beq mismatch3
cmp #"Y"
bne again$
jsr CHROUT
jsr prns
dc.b 13, "WRITE D64 TO DISK? ", 18,"Y",146,"ES ",18,"N",146,"O ", 0
again2$ jsr getkey
cmp #"N"
beq mismatch3
cmp #"Y"
bne again2$
jsr OK_KEY
; =================================
#if CUSTOM
jsr initwriter
; =================================
#else
#if MACH == 64 || MACH == 128
lda outBurst
bne 11$ ; can perform burst write -> do not open file
#endif
ldx #<d64chan
ldy #>d64chan
lda #1
jsr SETNAM
lda #3
ldx outDrive
ldy #3 ; open 3,8,3,"#"
jsr SETLFS
jsr OPEN
ldx #15
jsr geterror
cmp #0
beq noerr2$
jmp diskerror
noerr2$
lda #"3"
jsr initbp
ldx #15
jsr geterror
cmp #0
beq noerr3$
jmp diskerror
noerr3$
#endif
11$ lda #4
sta d64mode
ldx #1
stx oTrack
dex
stx oSector
lda #2+1
sta countHi
lda #$ab+0 ; 683 sectors
sta countLo
jsr InitBuffer32k
lda flags+0
jsr PutBuffer
lda flags+1
jsr PutBuffer
ldy #2
d64loop$
jsr GetByte
jsr PutBuffer
iny
bne d64loop$
dec countLo
bne d64loop$
dec countHi
bne d64loop$
jsr FlushBuffer
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda outBurst
bne i0$ ; can perform burst write -> did not open file
#endif
lda #3
jsr CLOSE
#endif
i0$ ldx #15
jsr I0
#if 1
jsr prns
dc.b "SIZE: ", 0
lda #<outSize
ldy #>outSize
jsr showsize
jsr CR
jsr CLALL
jsr CLRCHN
#endif
jmp err ; leave
#endif /* V20 */
#if MACH != 20 && MACH != 16
;--------------- Implode (method 6) ------------------------
minMatchLen:
dc.b 2
DecodeSF: ; can change ROM
jsr GetByte
sta countLo
inc countLo
ldy #0
loop$ jsr GetByte
pha
lsr
lsr
lsr
lsr
tax
pla
and #15
clc
adc #1
loop1$ sta codelens,y
iny
dex
bpl loop1$
dec countLo
bne loop$
rts
Implode:
jsr prns
dc.b "IMPLODED", 13, 0
; initialize the history buffer to 0
jsr ClearBuffer
lda #2
sta minMatchLen
jsr BYTEALIGN
lda flags+0
and #4
beq noLitTree$
lda #3
sta minMatchLen
jsr DecodeSF ; can change ROM
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<literalTree
sta Places+0
lda #>literalTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy #1 ; 256 literals
lda #0
jsr CreateTree
beq tok1$
; invalid tree
rts
tok1$
noLitTree$
jsr DecodeSF ; can change ROM
lda #<impLengthTree
sta Places+0
lda #>impLengthTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy #0
lda #64
jsr CreateTree
beq tok2$
; invalid tree
rts
tok2$ jsr DecodeSF ; can change ROM
lda #<distanceTree
sta Places+0
lda #>distanceTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy #0
lda #64
jsr CreateTree
beq tok3$
; invalid tree
rts
tok3$
impLoop$
ldx #3
0$ lda outSize+0,x
cmp uncSize+0,x
bcc loopIt$ ; SIZE < size
;bne loopIt$
dex
bpl 0$
rts
loopIt$
jsr GetBit
bcs literal$
; lz77
lda flags+0
and #2
beq dict4k$
; dict8k
ldx #7
jsr READBITS
asl
sta offset+0
lda #<distanceTree
ldy #>distanceTree
jsr DecodeSFValue ; can change ROM
jmp dictok$
dict4k$
ldx #6
jsr READBITS
asl
asl
sta offset+0
lda #<distanceTree
ldy #>distanceTree
jsr DecodeSFValue ; can change ROM
lsr
ror offset+0
dictok$
lsr
ror offset+0
sta offset+1
inc offset+0
bne dok2$
inc offset+1
dok2$
lda #0
sta countHi
lda #<impLengthTree
ldy #>impLengthTree
jsr DecodeSFValue ; can change ROM
sta countLo
cmp #63
bne lenok$
ldx #8
jsr READBITS
;clc
adc countLo
sta countLo
bcc lenok$
inc countHi
lenok$ lda minMatchLen
clc
adc countLo
sta countLo
bcc lenok2$
inc countHi
lenok2$:
jsr CopyLz2 ; offset in (offset), length in countLo/Hi
jmp impLoop$
literal$:
lda flags+0
and #4
beq get8$
lda #<literalTree
ldy #>literalTree
jsr DecodeSFValue ; can change ROM
jmp litok$
get8$: ldx #8
jsr READBITS
litok$ jsr PutBuffer
jmp impLoop$
#if 0
Shrink:
jsr prns
dc.b "SHRINK IS NOT SUPPORTED RIGHT NOW", 13, 0
rts
#else
;--------------- Shrink (method 1) - lzw ---------------------
codesize:
dc.b 0
KwKwK:
dc.b 0
code:
dc.w 0
oldcode:
dc.w 0
freecode:
dc.w 0
curcode:
dc.w 0
ReadCode:
ldx #8
jsr READBITS
sta code+0
ldx codesize ; it is at least 1
jsr READBITS
sta code+1 ; MSB
rts
CodeToOldcode:
lda code+0
sta oldcode+0
lda code+1
sta oldcode+1
rts
Shrink:
jsr prns
dc.b "SHRINK ", 0
ldx #1
stx codesize
stx freecode+1
dex ; X = 0
stx freecode+0
; Parent[] at buf32kEnd - 16384 (lo) / buf32kEnd - 8192 (hi)
; Value[] at buf32kEnd - 24576
; Stack[] at buf32kEnd - 32768
; for (code=0; code < BOGUSCODE /*256*/; code++) {
;ldx #0
0$ txa
sta buf32k+bufsz-24576,x ; Value[code] = code;
lda #0
sta buf32k+bufsz-16384,x ; Parent[code] lo
lda #1
sta buf32k+bufsz-8192,x ; Parent[code] = BOGUSCODE/*256*/;
inx
bne 0$
; for (code = BOGUSCODE+1; code < HSIZE; code++)
; Parent[code] = FREE_CODE;
lda #<(buf32k+bufsz-8192+257)
sta zp0
lda #>(buf32k+bufsz-8192+257)
sta zp1 ; Parent[BOGUSCODE+1] hi
lda #<(8192-257+1)
sta countLo
lda #>(8192-257+256)
sta countHi
ldy #0
;inc countLo
;inc countHi
lda #$20 ; FREE_CODE -- only hi byte matters
jmp 2$
1$ sta (zp0),y
iny
bne 2$
inc zp1
2$ dec countLo
bne 1$
dec countHi
bne 1$
; oldcode = READBITS(8);
; oldcode |= (READBITS(codesize)<<8);
jsr ReadCode
jsr CodeToOldcode
; if (SIZE < size) {
; ADDBUFFER(oldcode, outfp);
ldx #3
3$ lda outSize+0,x
cmp uncSize+0,x
bcc canAdd$ ; SIZE < size
dex
bpl 3$
rts
canAdd$:
lda oldcode+0
jsr PutBufferLzw
; while (SIZE < size) {
shrinkLoop$
ldx #3
4$ lda outSize+0,x
cmp uncSize+0,x
bcc loopIt$ ; SIZE < size
dex
bpl 4$
rts
loopIt$
; code = READBITS(8);
; code |= (READBITS(codesize)<<8);
jsr ReadCode
; if (code == BOGUSCODE) { /* possible to have consecutive escapes? */
;lda code+1
cmp #1
beq chk$
nob$ jmp noBogus$
chk$ lda code+0
bne nob$
; code == BOGUSCODE /*256*/
; code = READBITS(8);
; code |= (READBITS(codesize)<<8);
jsr ReadCode
;lda code+1
cmp #0
bne shrinkLoop$
lda code+0
cmp #1
bne notOne$
inc codesize ; codesize++;
jmp shrinkLoop$
notOne$ cmp #2
bne shrinkLoop$
; /* clear leafs (nodes with no children) */
; /* first loop: mark each parent as such */
lda #<(buf32k+bufsz-16384+257)
sta bTmp+0
lda #>(buf32k+bufsz-16384+257)
sta bTmp+1 ; Parent[BOGUSCODE+1] lo
lda #<(buf32k+bufsz-8192+257)
sta zp0
lda #>(buf32k+bufsz-8192+257)
sta zp1 ; Parent[BOGUSCODE+1] hi
lda #<(8192-257+1)
sta countLo
lda #>(8192-257+256)
sta countHi
ldy #0
;inc countLo
;inc countHi
jmp 92$
; for (code = BOGUSCODE+1; code < HSIZE; ++code) {
; curcode = (Parent[code] & CODE_MASK);
91$ lda (zp0),y ; Parent[] hi
and #$1f
beq 93$ ; <BOGUSCODE
cmp #1
bne 94$ ; >BOGUSCODE
lda (bTmp),y ; Parent[] lo
beq 93$ ; ==BOGUSCODE
; if (curcode > BOGUSCODE)
; Parent[curcode] |= HAS_CHILD;
94$ lda (bTmp),y
clc
adc #<(buf32k+bufsz-8192) ; Parent[] hi
sta offset+0
lda (zp0),y
and #$1f
adc #>(buf32k+bufsz-8192)
sta offset+1
sty y$+1
ldy #0
lda (offset),y
ora #$40 ; HAS_CHILD
sta (offset),y
y$ ldy #0
93$ iny
bne 92$
inc bTmp+1
inc zp1
92$ dec countLo
bne 91$
dec countHi
bne 91$
; /* second loop: clear all nodes *not* marked as parents; reset flag bits */
lda #<(buf32k+bufsz-8192+257)
sta zp0
lda #>(buf32k+bufsz-8192+257)
sta zp1 ; Parent[BOGUSCODE+1] hi
lda #<(8192-257+1)
sta countLo
lda #>(8192-257+256)
sta countHi
ldy #0
;inc countLo
;inc countHi
jmp 82$
; for (code = BOGUSCODE+1; code < HSIZE; ++code) {
; if (Parent[code] & HAS_CHILD) { /* just clear child-bit */
; Parent[code] &= ~HAS_CHILD;
81$ lda (zp0),y ; Parent[] hi
and #$40
beq free$
lda (zp0),y
and #$3f
jmp 83$
; } else { /* leaf: lose it */
; Parent[code] = FREE_CODE;
free$ lda #$20
; low part does not matter
83$ sta (zp0),y
iny
bne 82$
inc bTmp+1
inc zp1
82$ dec countLo
bne 81$
dec countHi
bne 81$
; freecode = BOGUSCODE;
ldx #0
stx freecode+0
inx
stx freecode+1
jmp shrinkLoop$
noBogus$
; newstr = &Stack[HSIZE-1];
lda #<(buf32k+bufsz-32768+8191)
sta bTmp+0
lda #>(buf32k+bufsz-32768+8191)
sta bTmp+1 ; &Stack[8192-1]
lda #0
sta KwKwK ; KwKwK = 0;
sta countLo
sta countHi ; len = 0;
; if (Parent[curcode = code] == FREE_CODE) {
lda code+0
sta curcode+0
clc
adc #<(buf32k+bufsz-8192) ; Parent[] hi
sta get$+1
lda code+1
sta curcode+1
adc #>(buf32k+bufsz-8192)
sta get$+2
get$ lda $aaaa
cmp #$20 ; low part does not matter
bne noKwKwK$
inc KwKwK ; KwKwK = 1;
inc countLo ; len = 1;
lda bTmp+0 ; newstr--;
bne ov$
dec bTmp+1
ov$ dec bTmp+0
lda oldcode+0 ; curcode = oldcode
sta curcode+0
lda oldcode+1
sta curcode+1
noKwKwK$:
; do {
; *newstr-- = Value[curcode];
; len++;
; curcode = (Parent[curcode] & CODE_MASK);
; } while (curcode != BOGUSCODE);
doLoop$ lda #<(buf32k+bufsz-24576)
clc
adc curcode+0
sta zp0
lda #>(buf32k+bufsz-24576)
adc curcode+1
sta zp1
ldy #0
lda (zp0),y
sta (bTmp),y ; *newstr = Value[curcode]
lda bTmp+0
bne ov2$
dec bTmp+1
ov2$ dec bTmp+0 ; newstr--;
inc countLo ; len++;
bne ov3$
inc countHi
ov3$
lda zp1
clc
adc #>8192
sta zp1 ; Value[curcode] -> Parent[curcode] lo
lda (zp0),y
sta curcode+0
lda zp1
clc
adc #>8192
sta zp1 ; Parent[curcode] lo -> hi
lda (zp0),y
and #$1f
sta curcode+1 ; curcode = (Parent[curcode] & CODE_MASK);
cmp #1
bne doLoop$
lda curcode+0
bne doLoop$ ; } while (curcode != BOGUSCODE);
inc bTmp+0
bne ov4$
inc bTmp+1 ; newstr++;
ov4$
; if (KwKwK)
; Stack[HSIZE-1] = *newstr;
lda KwKwK
beq noKwKwK2$
lda #<(buf32k+bufsz-32768+8191)
sta zp0
lda #>(buf32k+bufsz-32768+8191)
sta zp1
lda (bTmp),y
sta (zp0),y
noKwKwK2$:
; do {
; freecode++;
; } while (Parent[freecode] != FREE_CODE);
doLoop2$:
inc freecode+0
bne ov5$
inc freecode+1
ov5$ lda #<(buf32k+bufsz-8192) ; Parent[freecode] hi
clc
adc freecode+0
sta zp0
lda #>(buf32k+bufsz-8192)
adc freecode+1
sta zp1
lda (zp0),y
cmp #$20 ; low part does not matter
bne doLoop2$
; Parent[freecode] = oldcode;
; Value[freecode] = *newstr;
; oldcode = code;
lda oldcode+1
sta (zp0),y ; Parent[freecode] hi
lda zp1
sec
sbc #>8192
sta zp1
lda oldcode+0
sta (zp0),y ; Parent[freecode] lo
lda zp1
sec
sbc #>8192
sta zp1
lda (bTmp),y
sta (zp0),y ; Value[freecode]
jsr CodeToOldcode
; while (len--) {
; ADDBUFFER(*newstr, outfp);
; newstr++;
; }
lda bTmp+0
sta puta$+1
lda bTmp+1
sta puta$+2
inc countLo
inc countHi
jmp ov6$
puta$ lda $aaaa
jsr PutBufferLzw ; flushes at the right place
inc puta$+1
bne ov6$
inc puta$+2
ov6$ dec countLo
bne puta$
dec countHi
bne puta$
jmp shrinkLoop$
; Does not need to preserve Y
PutBufferLzw:
jsr PutBuffer ; Can switch ROM/RAM
lda outCmd+2
cmp #>(buf32k+bufsz-32768)
bne 2$
jsr FlushBuffer
jsr InitBuffer32k ; jsr + rts
2$ rts
#endif
;--------------- Reduce (methods 2-5) ------------------------
B: dc.b 0
dc.b 1,1,2,2,3,3,3,3, 4,4,4,4,4,4,4,4
dc.b 5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5
dc.b 6 ;,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6
;dc.b 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6
lastC: dc.b 0
state: dc.b 0
Reduce:
jsr prns
dc.b "REDUCE ", 0
lda method+0
clc
adc #47
jsr OK_KEY
; initialize the history buffer to 0
jsr ClearBuffer
jsr BYTEALIGN
; for (j=255; j>=0; j--) {
; N[j] = READBITS(6);
; if (N[j] > 32) {
; fprintf(errfp, "Follower set %d too large: %d\n", j, N[j]);
; N[j] = 32;
; }
; for (i=0; i<N[j]; i++) {
; S[j][i] = READBITS(8);
; }
; }
lda #<S
sta bTmp+0
lda #>S
sta bTmp+1
lda #255
sta countHi
fLoop$ ldy countHi
lda bTmp+0
sta SPtrLo,y
lda bTmp+1
sta SPtrHi,y
ldx #6
jsr READBITS
ldy countHi
sta N,y
cmp #0
beq fNext$
cmp #33
bcc fOk$
inc ferr
rts
fOk$ sta countLo
fIL$ ldx #8
jsr READBITS
ldy #0
sta (bTmp),y
inc bTmp+0
bne ptrOk$
inc bTmp+1
ptrOk$ dec countLo
bne fIL$
fNext$ dec countHi
ldy countHi
cpy #255
bne fLoop$
lda #>SPtrLo
cmp bTmp+1
bcc badFollower$ ; HI >
bne okFollower$ ; HI <
lda #<SPtrLo
cmp bTmp+0
bcs okFollower$ ; LO <=
badFollower$
jsr prns
dc.b "FOLLOWER OVERRUN", 0
inc ferr
rts
okFollower$
lda #0
sta lastC ; lastC = 0;
sta state ; state = 0;
; while (SIZE < size) {
reduceLoop$
ldx #3
4$ lda outSize+0,x
cmp uncSize+0,x
bcc loopIt$ ; SIZE < size
dex
bpl 4$
rts
loopIt$
ldy lastC
lda N,y
bne more$ ; if (!N[lastC]) {
get8$ ldx #8
jsr READBITS ; c = READBITS(8);
jmp state$
more$ ; } else {
jsr GetBit ; if (READBITS(1)) {
bcs get8$ ; c = READBITS(8);
; } else {
ldx N,y
lda B,x
tax
jsr READBITS
ldy lastC
clc
adc SPtrLo,y
sta bTmp+0
lda #0
adc SPtrHi,y
sta bTmp+1
ldy #0
lda (bTmp),y ; c = S[lastC][READBITS(B[N[lastC]])];
; }
; }
state$ sta lastC ; lastC = c;
ldx state ; switch (state) {
bne not0$ ; case 0:
cmp #144 ; if (c != 144)
beq incs$
jsr PutBuffer ; ADDBUFFER(c, outfp);
jmp reduceLoop$ ; else
incs$ inc state ; state = 1;
jmp reduceLoop$ ; break;
not0$ cpx #1
bne not1$ ; case 1:
cmp #0
beq add144$ ; if (c) {
inc state
ldx #0
stx offset+1
stx offset+0
ldx method+0
cpx #2 ; switch(level) {
bne lnot2$ ; case 2:
asl ; dist = (c >> 7)*256;
rol offset+1 ; len = 0x7f & c;
lsr
cmp #127 ; state = (len == 0x7f)?2:3;
jmp chk$ ; break;
lnot2$ cpx #3
bne lnot3$ ; case 3:
tax ; dist = (c >> 6)*256;
asl ; len = 0x3f & c;
rol offset+1 ; state = (len == 0x3f)?2:3;
asl
rol offset+1
txa
and #63
cmp #63
jmp chk$ ; break;
lnot3$ cpx #4
bne lnot4$ ; case 4:
tax ; dist = (c >> 5)*256;
lsr ; len = 0x1f & c;
lsr ; state = (len == 0x1f)?2:3;
lsr
lsr
lsr
sta offset+1
txa
and #31
cmp #31
jmp chk$ ; break;
lnot4$ tax ; case 5:
lsr ; dist = (c >> 4)*256;
lsr ; len = 0x0f & c;
lsr ; state = (len == 0x0f)?2:3;
lsr ; break;
sta offset+1
txa
and #15
cmp #15
chk$ beq 2$ ; }
inc state
2$ sta countLo
lda #0
sta countHi
jmp reduceLoop$
add144$ sta state ; } else {
lda #144 ; state = 0;
jsr PutBuffer ; ADDBUFFER(144, outfp);
jmp reduceLoop$ ; }
; break;
not1$ cpx #2
bne not2$ ; case 2:
clc ; len += c;
adc countLo
sta countLo
lda countHi
adc #0
sta countHi
inc state ; state = 3;
jmp reduceLoop$ ; break;
not2$ sec ; case 3:
adc offset+0 ; dist += c + 1;
sta offset+0
lda offset+1
adc #0
sta offset+1
lda countLo
clc
adc #3
sta countLo ; len += 3;
lda countHi
adc #0
sta countHi
jsr CopyLz2
; while(len--) {
; int c = buf32k[(bIdx - dist) & 0x7fff];
; ADDBUFFER(c, outfp);
; }
; state = 0;
; break;
;}
lda #0
sta state
jmp reduceLoop$
;}
;FLUSHBUFFER(outfp);
;BYTEALIGN();
;return 0;
;}
#endif /* V20 */
;--------------- Bit/byte input routines ---------------------
BYTEALIGN ; flush bit bucket
lda #1
sta bb
rts
GetByte ldx be ; get byte -- can change ROM
beq readblk$
read$ inc be
lda inBuf,x
rts
readblk$
#if MACH != 20 && MACH != 16
#if CUSTOM
lda d64mode
bmi getcustom$
#else
#if MACH == 64 || MACH == 128
lda inBurst
beq std$ ; can't use burst read -> faster to do it sequentially
lda inTrack
beq std$
; can use burst and t&s known -> use burst read
jsr BREAD
lda status
and #15
cmp #2
bcc 1$
ldx inTrack
lda inSector
jsr BERR
1$
lda inBuf+0 ; copy links for next read
sta inTrack
lda inBuf+1
sta inSector
ldx #2
stx be
bne read$
#endif
#endif
#endif /* V20 */
std$ ldx #2
jsr CHKIN
#if MACH == 64 || MACH == 128
lda IDE64present
bpl fill$ ; IDE64 not found
tya
pha
lda #IDE64BR
ldx #0
ldy #1
inc $d020
jsr IDE64BlockRead
pla
tay
bcc IDE64readback$
#endif ;Tried to read from a floppy...
fill$ jsr CHRIN
ldx be
sta inBuf,x
#if MACH == 64 || MACH == 128
sta $d020
#endif
#if MACH == 16 || MACH == 4
sta $ff19
#endif
#if MACH == 20
and #7
eor $900f
sta $900f
#endif /* V20 */
inc be
bne fill$
IDE64readback$
jsr CLRCHN
ldx #0
jmp read$
#if CUSTOM
getcustom$:
ldx #14
jsr CHKOUT
lda #"U"
jsr CHROUT
lda #"4" ; reader
jsr CHROUT
jsr CLRCHN
jsr initiec
jsr getbyte
cmp #2
bcc ok$
; disk error! TODO: handle it!
rts
ok$ sty y$+1
ldy #2
get$ jsr getbyte
sta inBuf,y
#if MACH == 64 || MACH == 128
sta $d020
#endif
#if MACH == 16 || MACH == 4
sta $ff19
#endif
#if MACH == 20
and #7
eor $900f
sta $900f
#endif /* V20 */
iny
bne get$
y$ ldy #0
ldx #2 ; skip sector link
stx be
jmp read$
#endif
GetBit lsr bb ; get a bit from bit bucket
beq 1$
rts
1$ sta a$+1 ; it is empty -> fill it
stx x$+1
jsr GetByte
x$ ldx #0
sec ; insert full marker
ror
sta bb
a$ lda #0
rts
GetBits lda #0 ;2 ; Reverse the order by not reversing the result..
1$ dex ;2
bmi 0$ ;2/3
lsr bb ;5
bne 2$ ;2/3
sta a$+1
stx x$+1
jsr GetByte
x$ ldx #0
sec
ror
sta bb
a$ lda #0
2$ rol ;2
jmp 1$ ;3
0$ rts ;19+ 17*#bits
READBITS ; Read X bits from the input, in Gzip order, returns C clear
stx j$+1 ;4
#if MACH != 20 && MACH != 16
lda #0
1$ dex
bmi 0$
lsr bb
bne 2$
sta a$+1
stx x$+1
jsr GetByte
x$ ldx #0
sec
ror
sta bb
a$ lda #0
2$ rol
jmp 1$
0$ ;7+17*#bits
#else
jsr GetBits ;19+17*#bits
#endif
; reverse bit pattern
; worst-case 25 cycles (0 bits), best-case 11 cycles (8 bits)
tay ;2
lda bitReverse,y ;4
; Logical shift right A by 8-X positions (X=0..8)
clc ;2
j$ bcc j$+2 ;3
lsr ; 0 -> 8 shifts
lsr ; 1 -> 7 shifts
lsr ; 2 -> 6 shifts
lsr ; 3 -> 5 shifts
lsr ; 4 -> 4 shifts
lsr ; 5 -> 3 shifts
lsr ; 6 -> 2 shifts
lsr ; 7 -> 1 shifts
rts ; 8 -> 0 shifts
; C is clear because 8-X top bits will be zero
; 43+15*#bits / 31+15*#bits
; 1 bits = 58 cycles, 8 bits = 163 cycles (~20 cycles/bit)
; (UnZip: 23+45*#bits)
;--------------- Output/buffer routines ---------------------
; 70+12 cycles/byte (w/ CRC32)
PutBuffer:
sty puty+1 ;4
inc outSize+0 ; (256*9+(256*8+(256*8+5)/256)/256)/256
bne 0$ ; = 9.0314 cycles/byte
inc outSize+1
bne 0$
inc outSize+2
bne 0$
inc outSize+3
0$
#if MACH == 20
ldy outCmd+2
bpl outCmd ; ok, less than $8000
; move $8000..9fff -> $a000..bfff
pha
tya
ora #$20
sta outCmd+2
pla
#endif
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
outCmd sta $aaaa
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 20
sty outCmd+2 ; restore "real" address
#endif
; updcrc()
; (crc32_tab[((int)crc ^ cp) & 255] ^ (crc >> 8))
eor CRC+0 ; 3
tay ; 2
lda crc32_tab0,y ; 4
eor CRC+1 ; 3
sta CRC+0 ; 3
lda crc32_tab1,y ; 4
eor CRC+2 ; 3
sta CRC+1 ; 3
lda crc32_tab2,y ; 4
eor CRC+3 ; 3
sta CRC+2 ; 3
lda crc32_tab3,y ; 4
sta CRC+3 ; 3 =42 cycles/byte = ~7.5 secs for 170.75kB
inc outCmd+1 ;6
bne 2$ ;2/3
inc outCmd+2
lda outCmd+2
cmp #>(buf32k+bufsz)
bne 2$
; Save buffer data buffer32k .. (outCmd)
jsr FlushBuffer
jsr InitBuffer32k
2$
puty ldy #0 ; restore Y value
rts
InitBuffer32k:
; Init buffer pointer
lda #<buf32k
sta outCmd+1
lda #>buf32k
sta outCmd+2
rts
#if MACH != 20 && MACH != 16
; Implode expects a cleared buffer
ClearBuffer:
lda #<buf32k
sta 0$+1
lda #>buf32k
sta 0$+2
lda #0
tay
0$ sta $aa00,y
iny
bne 0$
inc 0$+2
ldx 0$+2
cpx #>(buf32k+bufsz)
bne 0$
rts
#endif /* V20 */
FlushBuffer: ; Can trash A & Y, X
lda mode
cmp #"N" ; skip it
bne do$
rts
do$
#if MACH != 20 && MACH != 16
#if CUSTOM
lda d64mode
bpl donow$
jsr prns
dc.b "INSERT DESTINATION DISK & PRESS ",18,"D",146," ", 0
wait$ jsr getkey
cmp #"D"
bne wait$
jsr OK_KEY
donow$
#endif
jsr onoff
lda d64mode
beq no$
jsr writebuf
jsr CLRCHN
jsr onoff
#if CUSTOM
lda d64mode
bmi ask$
rts
ask$ jsr prns
dc.b "INSERT SOURCE DISK & PRESS ",18,"S",146," ", 0
wait2$ jsr getkey
cmp #"S"
bne wait2$
jmp OK_KEY
#else
rts
#endif
#endif /* V20 */
no$ ldx #3
jsr CHKOUT ; (sends LISTEN+SECOND)
lda #<buf32k
sta bTmp+0
lda #>buf32k
sta bTmp+1
1$
#if MACH == 64 || MACH == 128
lda IDE64present
bpl noIDE64here$ ; IDE64 not found
lda outCmd+1
sec
sbc bTmp+0
tax
lda outCmd+2
sbc bTmp+1
tay
lda #bTmp
inc $d020
jsr IDE64BlockWrite
bcc IDE64writeback$ ;Tried to write to a floppy...
noIDE64here$
#endif
lda bTmp+0
cmp outCmd+1
bne 0$
lda bTmp+1
cmp outCmd+2
bne 0$
IDE64writeback$
jsr CLRCHN
jmp onoff
0$
#if MACH == 20
lda bTmp+1
pha
bpl base$ ; ok, less than $8000
; move $8000..9fff -> $a000..bfff
ora #$20
sta bTmp+1
base$
#endif /* V20 */
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
ldy #0
lda (bTmp),y
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
sta $ff19
jsr CHROUT
#endif
#if MACH == 64 || MACH == 128
sta $d020
jsr CHROUT
#endif
#if MACH == 20
pha
jsr CHROUT
pla
and #7
eor $900f
sta $900f
pla
sta bTmp+1 ; restore "real" address
#endif /* V20 */
inc bTmp+0
bne 1$
inc bTmp+1
jmp 1$
;--------------- Huffman routines ---------------------
;================================================================
;
; struct HufNode
; 0 0-bit value LSB
; 1 0-bit value MSb (D0) + leaf flag (D7)
; 2 1-bit value LSB or jump LO
; 3 1-bit value MSb (D0) + leaf flag (D7) or jump HI (D7=0)
;UnZip: create huffman codes 299 bytes (gunzip 397(new 202) bytes)
IsPat ; Check if there is another code of the current length
; while (1) {
; if (fpos[len] >= fmax)
; return -1;
; if (flens[fpos[len]] == len)
; return fpos[len]++;
; fpos[len]++;
; }
lda len
asl
tax
loop$ ldy fpos+0,x
lda fpos+1,x ; fpos[len]
cmp numval+1
bcc 0$
cpy numval+0
beq not$
0$ cmp #0 ; HI
bne 1$
lda (lengths),y
jmp 2$
1$ inc lengths+1 ; next page
lda (lengths),y
dec lengths+1
2$ cmp len
bne inc$
; got it
lda fpos+1,x
lsr ; shift HI to C
tya ; LO to A
inc fpos+0,x
bne 3$
inc fpos+1,x
3$ ldx #0 ; return zero set (and negative clear)
rts
inc$ inc fpos+0,x
bne loop$
inc fpos+1,x
bpl loop$
not$ ldx #128 ; return zero clear (and negative set)
rts
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
CreateTree
sta numval+0
sty numval+1
lda #0
sta len
ldx #2*17-1 ; clear the index counters
0$ sta fpos,x
dex
bpl 0$
; Recursive function
; max recursion depth is equal to the length of the longest codeword (16?)
; four bytes of stack are used for each recursion (4*16 = 64)
Rec lda len
cmp #17
bne ok$
inc ferr ; invalid huffman tree
; Z clear
rts
ok$ lda curplace+0 ; Save old curplace
pha
lda curplace+1
pha
lda Places+1
sta curplace+1
lda Places+0
sta curplace+0 ; curplace = Places
clc
adc #4 ; Places++
sta Places+0
bcc 0$
inc Places+1
0$ inc len ; len++;
jsr IsPat ; Is there a code of this length?
bne notzr$
; Yes: set leaf node indicator and value
ldy #0
sta (curplace),y ; 0-branch LSB
lda #$40
rol ; <-C $80+C leaf cell + MSb
iny
sta (curplace),y ; 0-branch MSb
bpl one$ ; jump always
notzr$ ; No: clear the leaf node indicator and
; create the 0-bit subtree recursively
ldy #1
tya ;lda #0 ; non-negative is enough
sta (curplace),y ; not a leaf cell
jsr Rec
jmp notone$ ; will not find a code because there was none left
one$ jsr IsPat ; Is there a code of this length?
bne notone$
; Yes: set leaf node indicator and value
ldy #2
sta (curplace),y ; 1-branch LSB
lda #$40
rol ; <-C $80+C leaf cell + MSb
iny
sta (curplace),y ; 1-branch MSb
bpl out$
notone$ ; No: set jump address and
; create the 1-bit subtree recursively
ldy #3
lda Places+1 ; not a leaf cell
sta (curplace),y ; (must be in lower half of the mem)
dey
lda Places+0
sta (curplace),y
jsr Rec
out$ dec len ; len--;
; Restore curplace
pla
sta curplace+1
pla
sta curplace+0
lda ferr ; Z set/clear
rts
; UnZip: 0-bit 27+13 1-bit 46+13 ->36.5+13 (gunzip 31/39-5 ->35-5)
; 48 bytes (gunzip 56 bytes)
; Decode a value using a tree that is in A(lo) and Y(hi)
; 12(jsr+rts) + 6 + ~34 cycles / decoded bit
DecodeValue
sta curplace+0 ; 3
sty curplace+1 ; 3
while$ ; GetBit Note: does not need to save A nor X!!
lsr bb ; 5
beq more$ ; 2 /3
bcc zero$ ; 2/3 zero:~30 one:~38
; A one-bit ; last:~29+6 last:~28+6
one$ ldy #3 ; 2
lda (curplace),y ; 5*
bmi return ; 2/3
tax ;2
dey ;2
lda (curplace),y ;5*
sta curplace+0 ;3
stx curplace+1 ;3
bcs while$
;jmp while$ ;3 =18
more$ jsr GetByte
sec
ror
sta bb
bcc zero$
bcs one$
zero$ ldy #1 ; 2
lda (curplace),y ; 5*
bmi return ; 2/3
lda curplace+0 ; 3
;clc
adc #4 ; 2
sta curplace+0 ; 3
bcc while$ ; 2/3
inc curplace+1 ; 5
bcs while$
;jmp while$ ; 3
; return curplace->b1 or curplace->b0
return lsr ; 2 MSb to C
dey ; 2
lda (curplace),y ; 5* LSB to A
rts ; 6
#if MACH != 20 && MACH != 16
; Decode a value using a tree that is in A(lo) and Y(hi)
; ~35 cycles / decoded bit
DecodeSFValue ; can change ROM
sta curplace+0 ; 3
sty curplace+1 ; 3
while$ ; GetBit Note: does not need to save A nor X!!
lsr bb ; 5
bne 1$ ; 2/3
jsr GetByte
sec
ror
sta bb
1$ bcs zero$ ; 2/3 zero:~31 one:~39
; A one-bit ; last:~30+6 last:~29+6
ldy #3 ; 2
lda (curplace),y ; 5*
bmi return ; 2/3
tax ;2
dey ;2
lda (curplace),y ;5*
sta curplace+0 ;3
stx curplace+1 ;3
bcc while$
;jmp while$ ;3 =18
zero$ ldy #1 ; 2
lda (curplace),y ; 5*
bmi return ; 2/3
lda curplace+0 ; 3
;sec
adc #3 ; 2
sta curplace+0 ; 3
bcc while$ ; 2/3
inc curplace+1 ; 5
bcs while$
;jmp while$ ; 3
#endif /* V20 */
;--------------- Misc utility routines ---------------------
puthex pha
lsr
lsr
lsr
lsr ; 0..9 -> $30..$39, A..F -> $41..$46
#if 1
cmp #10
bcc d1$
adc #$70-10
d1$ eor #$30
#else
tay
lda hex,y
#endif
jsr CHROUT
pla
and #15
#if 1
cmp #10
bcc d2$
adc #$70-10
d2$ eor #$30
jmp CHROUT
#else
tay
lda hex,y
jmp CHROUT
hex dc.b "0123456789"
dc.b "ABCDEF"
#endif
showsize:
sta 0$+1
sty 0$+2
jsr CLRCHN
ldx #3
0$ lda $aaaa,x
bne 1$
cpx #3
beq 2$ ; do not show the first "00"
1$ jsr puthex
2$ dex
bpl 0$
rts
onoff lda $d011
eor #$10
sta $d011
rts
putstr cpy #0
beq 2$
stx 0$+1
sta 0$+2
sty 1$+1
jsr CLRCHN
ldy #0
0$ lda $aaaa,y
jsr CHROUT
iny
1$ cpy #0
bne 0$
2$ rts
getstr sta 0$+1 ; <buffer
sta 2$+1
stx 0$+2 ; >buffer
stx 2$+2
sty 1$+1 ; maxlen+1
jsr CLRCHN
ldy #0
0$ lda $aaaa,y
beq edit$
jsr CHROUT
iny
bne 0$
edit$ sty 3$+1
jsr getkey
3$ ldy #0
bcs edit$
cmp #13 ; return
beq quit$
cmp #157 ; cursor left
beq bs$
cmp #20 ; backspace
bne no8$
bs$ cpy #0
beq edit$
jsr CHROUT ; <- destructive bs?
dey
jmp edit$
no8$ cmp #32
bcc edit$ ; 0..31
1$ cpy #0
beq edit$ ; no more room
2$ sta $aaaa,y
jsr CHROUT
iny
jmp edit$
quit$ rts
getkey jsr CLRCHN
jsr GETIN
clc
bne ok$
sec
ok$ rts
geterror: ; read the disk error channel - channel in X
jsr CHKIN
#if MACH == 16 || MACH == 4
ldy #30
11$ dey
bpl 11$
#endif
jsr CHRIN ; read the first digit
sta errorStr+0
and #15
tax ; and store it
jsr CHRIN ; read the second digit
sta errorStr+1
and #15
clc
adc tentimes,x
sta errorCode
pha
;beq skip$ ; no error -> do not read the rest
ldy #2
2$ jsr CHRIN
sta errorStr,y
iny
cmp #$0d ; IDE64 does not set ST at the end of the error string
beq 3$
lda ST ; READST
beq 2$
3$ sty errorLen
skip$ jsr CLRCHN ; clear the channel
pla
rts ; return (error code in accumulator)
#if MACH != 20 && MACH != 16
sectorsPerTrack:
dc.b 21,21,21,21,21,21,21,21 ;1..8
dc.b 21,21,21,21,21,21,21,21 ;9..16
dc.b 21,19,19,19,19,19,19,19 ;17..24
dc.b 18,18,18,18,18,18,17,17 ;25..32
dc.b 17,17,17 ;33..35
;dc.b 21,21,21,21,21,21,21,21 ;36..43
;dc.b 21,21,21,21,21,21,21,21 ;44..51
;dc.b 21,19,19,19,19,19,19,19 ;52..59
;dc.b 18,18,18,18,18,18,17,17 ;60..67
;dc.b 17,17,17 ;68..70
oTrack dc.b 1
oSector dc.b 0
oPages dc.b 0
#endif
putval pha ; 0..99 decimal
lda #" "
jsr CHROUT
pla
ldx #0
1$ cmp #10
bcc 0$
inx
sec
sbc #10
jmp 1$
0$ cpx #0
beq 2$ ; turn off leading zero
pha
txa
clc
adc #"0"
jsr CHROUT
pla
2$ clc
adc #"0"
jmp CHROUT
#if MACH != 20 && MACH != 16
writebuf:
lda #<buf32k
sta bTmp+0
lda #>buf32k
sta bTmp+1
lda outCmd+2
sec
sbc #>buf32k
sta oPages
; ===============================
#if CUSTOM
; I/O constants and the variables
iecport1 = $dd00 ;$912c
dato = 32 ;32
clko = 16 ;2
iecport2 = $dd00 ;$911f
atno = 8 ;128
clki = 64 ;1
dati = 128 ;2
#if 0
ldx #15
jsr CHKOUT
lda #"U"
jsr CHROUT
lda #"5" ; writer
jsr CHROUT
jsr CLRCHN ; does not seem to work. Timing?
#else
lda outDrive
jsr LISTEN
lda #$6f
jsr SECOND
lda #"U"
jsr CIOUT
lda #"5" ; writer
jsr CIOUT
jsr UNLSN
#endif
jsr initiec
ldy #40
ww$ inc $d020 ; enough delay for a slow drive to execute U5
dec $d020
dey
bpl ww$
#endif
; ===============================
wrloop$ lda oPages
bne wrcnt$
#if CUSTOM
lda #0 ; send EOF
jsr putbyte
#endif
rts
nosector$
lda #0
sta oSector
inc oTrack
wrcnt$ lda d64mode
#if CUSTOM == 0
cmp #8
bne d7141$
lda oSector
cmp #40
beq nosector$ ; no sector 40 -> next track, sector 0
bne yessector$
#endif
d7141$ lda oTrack
cmp #36
bcc cmp$ ; 1..35
sbc #35 ; 36..70 -> 1..35
cmp$ tax
lda oSector
cmp sectorsPerTrack-1,x
bcs nosector$
yessector$
; Write the block @oScnt into oTrack / oSector + oScnt
; ===============================
#if CUSTOM
lda oTrack
jsr putbyte
lda oSector
jsr putbyte
ldy #0
send$
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
lda (bTmp),y
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
sta $ff19
#endif
#if MACH == 64 || MACH == 128
sta $d020
#endif
jsr putbyte
iny
bne send$
;lda #14
;sta $d020
; ===============================
#else
#if MACH == 64 || MACH == 128
lda outBurst
beq nob$
again$ jsr BSAVE ; can perform burst write -> did not open file
lda status
and #15
cmp #2
bcc next$
cmp #11
bne berr$
ldx #15
jsr BINQ
jmp again$
berr$ ldx oTrack
lda oSector
jsr BERR
lda #13
jsr CHROUT
jmp next$
#endif
nob$ ldx #3
jsr CHKOUT ;(sends LISTEN+SECOND)
ldy #0
send$
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
lda (bTmp),y
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
sta $ff19
jsr CHROUT
#endif
#if MACH == 64 || MACH == 128
sta $d020
jsr CHROUT
#endif
iny
bne send$
jsr CLRCHN
ldx #15
jsr CHKOUT
lda #"U"
jsr CHROUT
lda #"2"
jsr CHROUT
lda #" "
jsr CHROUT
lda #"3" ; channel
jsr CHROUT
lda #" "
jsr CHROUT
lda #"0" ; unit
jsr CHROUT
lda oTrack ; track
jsr putval
lda oSector ; sector
jsr putval
jsr CLRCHN
lda #14
sta $d020
ldx #15
jsr geterror ; waits until the write is finished..
cmp #0
beq noerr$
jmp diskerror
noerr$
#endif
next$ inc bTmp+1
dec oPages
inc oSector
jmp wrloop$
#if CUSTOM
#else
initbp pha
ldx #15
jsr CHKOUT
lda #"B"
jsr CHROUT
lda #"-"
jsr CHROUT
lda #"P"
jsr CHROUT
lda #" "
jsr CHROUT
pla
jsr CHROUT
lda #" "
jsr CHROUT
lda #"0"
jsr CHROUT
jmp CLRCHN
#endif
#endif /* V20 */
#if MACH != 128
prns jsr CLRCHN
pla
sta addr$+1
pla
sta addr$+2
loop$ inc addr$+1
bne addr$
inc addr$+2
addr$ lda $aaaa
beq out$
jsr CHROUT
jmp loop$
out$ lda addr$+2
pha
lda addr$+1
pha
rts
#endif
#if CUSTOM == 1
; =========================================================================
; the drive code
; =========================================================================
drvcode:
#rorg $500
;---------------------------------------
; The fastload routine for the drive
;---------------------------------------
;---------------------------------------
; FOR 1540/41/70/71
;---------------------------------------
acsbf0 = $00
acsbf = $01 ; access to buffer 1
trkbf0 = $06
trkbf = $08 ; track of buffer 1
sctbf0 = $07
sctbf = $09 ; sector of buffer 1
iddrv0 = $12 ; id of drive 0
id = $16 ; id
via1pb = $1800
via2pb = $1c00
buf0 = $0300
buf = $0400 ; sector buffer (for job 1)
buf2 = $0700
datbf = $14 ; databuffer - temporary
drive:
U3$
rtrack dc.b 0
rsector dc.b 0
retries dc.b 0
U4$ jmp reader$
U5$ cld
cli ; interrupts enabled until first sector read
lda #0
sta acsbf
;lda #8
;ora via2pb
;sta via2pb ; turn the LED on
jsr led$
sectloop$
jsr recv$ ; get track #
;cmp #0
sta trk$+1
beq eof$
jsr recv$ ; get sector #
sta sct$+1
lda #0
sta buf$+1 ; reset counter
loop$ jsr recv$
buf$ sta buf2
inc buf$+1
bne loop$
eof$ lda #10
sta retries
wait$ lda acsbf
bmi wait$
cmp #2
bcc oldok$
dec retries
bmi err$
di$ cmp #11 ; disk ID mismatch
bne retry$
lda id ; tolerate disk id changes
sta iddrv0
lda id+1
sta iddrv0+1
retry$ lda retries
cmp #5
bne nknock$
lda #$c0
sta acsbf ; half the retries left: knock the head (seek track 1)
poll2$: lda acsbf ; wait for the command to complete
bmi poll2$
nknock$ lda #$90 ; code for writing the sector
sta acsbf
jmp wait$ ; retry
err$ ldx acsbf
flash$
;lda #8
;ora via2pb
;sta via2pb ; turn the LED on
jsr led$
jsr delay$
;lda #$f7
;and via2pb
;sta via2pb ; turn the LED off
jsr led$
jsr delay$
dex
bne flash$
jsr delay$
jsr delay$
jmp err$
delay$ lda #200
ldy #0
del2$ dey
bne del2$
;sec
sbc #1
bne del2$
rts
oldok$
sct$ lda #0
sta sctbf
trk$ lda #1
sta trkbf
bne ok$
jmp led$
;lda #$f7
;and via2pb
;sta via2pb ; turn the LED off
;rts ; EOF
ok$
ldy #127
loop2$ lda buf2,y
sta buf,y
lda buf2+$80,y
sta buf+$80,y
dey
bpl loop2$
lda #$90 ; code for writing the sector
sta acsbf
jmp sectloop$
reader$
lda #10
sta retries
jsr led$
;lda #$08
;ora via2pb
;sta via2pb ; turn the LED on
lda rtrack
sta trkbf0
lda rsector
sta sctbf0
again$ lda #$80 ; read sector command
sta acsbf0
poll$ lda acsbf0
bmi poll$
cmp #2
bcc rok$
cmp #11 ; disk ID mismatch
bne rerr$
lda id ; tolerate disk id changes
sta iddrv0
lda id+1
sta iddrv0+1
jmp again$ ; retry
rerr$ dec retries
bne again$
jmp send$ ; send error code and nothing more
rok$ jsr send$ ; send 0 or 1
lda #2
sta rloop$+1 ; start from buf0+2
rloop$ lda buf0+2
jsr send$
inc rloop$+1
bne rloop$ ; send the block, not including link
lda buf0+0
sta rtrack
lda buf0+1
sta rsector
jmp led$
;lda #$f7
;and via2pb
;sta via2pb ; turn the LED off
;rts
send$ sta datbf
ldx #8 ; send 8 bits
sendb$ lsr datbf ; read next bit
lda #2 ; prepare for CLK=high, DATA=low
bcs sskip$
lda #8 ; prepare for CLK=low, DATA=high
sskip$ sta via1pb ; send the data
sack$ lda via1pb ; wait for CLK==DATA==low
and #5
eor #5
bne sack$
sta via1pb ; set CLK=DATA=high
lda #5
swait$ bit via1pb
bne swait$ ; wait for CLK==DATA==high
dex
bne sendb$ ; loop until all bits have been sent
rts
led$ lda #8
eor via2pb
sta via2pb ; toggle LED
rts
;---------------------------------------
; recv$ receives a byte to A. datbf is used as temporary storage.
recv$ sei
ldy #10 ; CLK=low, DATA=low
ldx #8 ; counter: receive 8 bits
recvbit$
rwait$ lda #$85
and via1pb ; wait for CLK==low || DATA==low
beq rwait$
sty via1pb ; CLK=low, DATA=low, one of them is low already
lsr ; read the data bit
ror datbf ; and store it
bit $24
lda #0
dex
; There must be at least 8 C64-cycles between via1pb writes (35 max),
; so that C64 has time to detect it.
; Here there are 18 cycles (@2MHz 17 needed)
sta via1pb ; set CLK=DATA=high
bne recvbit$ ; loop until all bits have been received
lda datbf ; read the data to A
cli
rts
edrvcode
#rend
getbyte ldx #8 ; counter: get 8 bits
getbit lda iecport2
and #dati | clki
eor #dati | clki
beq getbit ; wait for CLK==low || DATA==low
#if dati == 128
asl ; Carry = DATA==low
#else
#if dati < clki
and #dati
#endif
cmp #dati
#endif
iec0d1a lda #255 - dato
bcs gskip$
eor #dato | clko
gskip$ sta iecport1 ; acknowledge the bit
ror zp1 ; store the data
lda #dati | clki
wgack$ bit iecport2
beq wgack$ ; wait for CLK==high || DATA==high
iec1d1a lda #255 - clko - dato
sta iecport1 ; raise CLK and DATA
dex
bne getbit ; loop until all bits are received
lda zp1
rts
putbyte sei
sta zp0
sty ystore+1
iec1d1 ldy #255 - clko - dato
ldx #8 ; counter: send all 8 bits
putbit lsr zp0 ; read a bit
iec0d1 lda #255 - dato
bcc bit0
eor #dato | clko
bit0 sta iecport1 ; send the data
lda #dati | clki
wack0$ bit iecport2
bne wack0$ ; wait for CLK==DATA==low
sty iecport1 ; set DATA=CLK=high
dex
bne putbit ; loop until all bits are sent
cli
ystore ldy #0
rts
; =========================================================================
; Initializations and the disk drive's part of the fastloader.
; =========================================================================
AMOUNT = $20 ; amount of data bytes to transfer with one M-W command
initwriter:
lda inTrack
sta drvcode+0
lda inSector
sta drvcode+1
; send the m-w command to write the data
lda #AMOUNT
sta mwcmd$+0
lda #>drive
sta mwcmd$+1
lda #<drive
sta mwcmd$+2
lda #<drvcode
sta mwbyte$+1
lda #>drvcode
sta mwbyte$+2
mwloop$ ldx #15
jsr CHKOUT ;(sends LISTEN+SECOND)
ldx #lmwcmd$ - 1
smwcmd$ lda mwcmd$,x
jsr CIOUT
dex
bpl smwcmd$
; send the actual data bytes
ldx #0
mwbyte$ lda drvcode,x
jsr CIOUT
inx
cpx #AMOUNT
bne mwbyte$
; complete the command
jsr UNLSN
; update the addresses
clc
lda #AMOUNT
adc mwbyte$ + 1
sta mwbyte$ + 1
bcc noupdhi1$
clc
inc mwbyte$ + 2
noupdhi1$
lda #AMOUNT
adc mwcmd$ + 2
sta mwcmd$ + 2
tax
lda #0
adc mwcmd$ + 1
sta mwcmd$ + 1
cpx #<edrvcode
sbc #>edrvcode
bcc mwloop$
rts
mwcmd$ dc.b AMOUNT,>drive,<drive,"W-M"
lmwcmd$ = . - mwcmd$
initiec:
lda iecport1
and #255 - dato - clko
sta iec1d1+1 ; CLK=1, DATA=1
sta iec1d1a+1 ; CLK=1, DATA=1
eor #clko
sta iec0d1+1 ; CLK=0, DATA=1
sta iec0d1a+1 ; CLK=0, DATA=1
rts
#endif /* CUSTOM */
#if MACH != 20 && MACH != 16
;--------------- Directory scan/list routine ---------------------
dir dc.b "$0:*"
fname ds.b 17
fnameln dc.b 0
ftype dc.b 0
ftrack dc.b 0
fsector dc.b 0
fblocks dc.b 0,0
ftypstr dc.b "SEQ PRG USR REL CBM ?6? ?7? "
fcount dc.b 0
fdos dc.b 0
fflag dc.b 0
fdtype dc.b 0
I0 ; command channel in X
jsr CHKOUT
lda #"I"
jsr CHROUT
lda #"0"
jsr CHROUT
jmp CLRCHN
ReadDir ;ldx #14
;jsr I0
lda #0
sta fcount
sta fdtype
; Open directory
ldx #<dir
ldy #>dir
lda #4
jsr SETNAM
lda #2 ; first try raw directory
ldx inDrive
ldy #2 ; open 2,8,2,"$0:*"
jsr SETLFS
jsr OPEN
lda ST
beq 2$
lda #2
jsr CLOSE
lda #2 ; could not open raw, try normal directory
ldx inDrive
ldy #0 ; open 2,8,0,"$0:*"
jsr SETLFS
jsr OPEN
inc fdtype
lda ST
beq 2$
quit0$ lda #2
jsr CLOSE
jsr CLRCHN
ldx #14
jsr geterror
ldx #<errorStr
lda #>errorStr
ldy errorLen
jmp putstr
2$ ldx #2
jsr CHKIN
jsr CHRIN ; get disk format "A" for 1541/51/71/4040 or "D" for 1581
sta fdos
jsr CHRIN
sta fflag
cmp #$04
bne notide$
lda fdos
cmp #$01
bne notide$
; probably IDE64 or some other device that does not support
; raw directories
inc fdtype
ldy #5
is0$ jsr CHRIN
dey
bne is0$ ; skip line link, line number, reverse
is1$ jsr CHRIN
cmp #0 ; skip the rest of the line
bne is1$
jsr CLRCHN
jmp dirloop$
notide$
ldy #252
skip$ jsr CHRIN
dey
bne skip$ ; skip disk info
jsr CLRCHN
dirloop$
ldx #2
jsr CHKIN
lda fdtype
bne ide2$
jmp noide2$
ide2$ jsr CHRIN ; skip line link
jsr CHRIN
jsr CHRIN
sta fblocks+0
jsr CHRIN
sta fblocks+1
is3$ jsr CHRIN
tax
beq ret$ ; xx BLOCKS FREE. -- zero before quote
lda ST
bne ret$
cpx #34
bne is3$
ldy #0
is4$ jsr CHRIN ; name
cmp #34
beq is5$
sta fname,y
iny
cpy #17
bne is4$
dey
is5$ lda #0
sta fname,y
sty fnameln
is6$ jsr CHRIN
iny
cpy #18
bne is6$
ldx #$81
cmp #"S" ; "SEQ"
beq is7$
inx
cmp #"P" ; "PRG"
beq is7$
inx
cmp #"U" ; "USR"
beq is7$
inx
cmp #"R" ; "REL"
beq is7$
inx
cmp #"C" ; "CBM"
beq is7$
cmp #"D" ; "DIR" (IDE64)
beq is7$
ldx #$80 ; "DEL"
is7$
stx ftype
is8$ jsr CHRIN
ldx ST
bne ret$
tax ; cmp #0
bne is8$
sta ftrack
sta fsector
jmp noskip$
ret$ lda #2
jsr CLOSE
jmp CLRCHN ; jsr + rts
noide2$ jsr CHRIN ; file type 0
sta ftype
lda ST
and #$c0
beq ok$
lda #2
jsr CLOSE
jmp CLRCHN ; jsr + rts
ok$ jsr CHRIN ; track 1
sta ftrack
jsr CHRIN ; sector 2
sta fsector
ldy #0 ; 16
nameloop$
jsr CHRIN ; name 3-18 (0-15)
cmp #$a0
beq nameend$
sta fname,y
iny
cpy #16
bne nameloop$
lda #0
sta fname,y
sty fnameln
jmp other$
nameend$
lda #0
sta fname,y
sty fnameln
iny
other$ jsr CHRIN ; skip the rest of the filename & other fields
iny
cpy #25 ; 19-27 (16-24)
bne other$
jsr CHRIN ; blocks lo 28
sta fblocks+0
jsr CHRIN ; blocks hi 29
sta fblocks+1
inc fcount
lda fcount
and #7
beq noskip$
jsr CHRIN ; 'link' 30
jsr CHRIN ; 'link' 31
noskip$
jsr CLRCHN
lda ftype
and #7
bne cont$
jmp dirloop$ ; skip DELeted files
cont$ ldy inLen ; if no file specified, ask the user
beq ask$ ; if file specified, compare and return..
#if 1
cpy fnameln ; 21 bytes
beq cname$
jmp dirloop$ ; lengths do not match, no need to check more
cname$ lda fname-1,y
cmp inFile-1,y
beq 12$
jmp dirloop$ ; name does not match
12$ dey
bne cname$
#else
; Handle wildcard(s) 26 bytes
ldy #0
cname$ lda inFile,y
cmp "?"
beq 22$ ; skip one char
cmp "*"
beq gotit$ ; skip rest of name TODO: real *
cmp fname,y
beq 22$
jmp dirloop$
22$ iny
cpy fnameln
bne cname$
#endif
; name matches
gotit$
#if MACH != 20 && MACH != 16
lda ftrack
sta inTrack
lda fsector
sta inSector
#endif /* V20 */
lda #2
jmp CLOSE ; jsr + rts
ask$
#if 0
ldx #">"
lda ftype
and #64
bne locked$
ldx #32
locked$
txa
jsr CHROUT
#endif
lda fblocks+1
jsr puthex
lda fblocks+0
jsr puthex
lda #" "
jsr CHROUT
lda ftype
and #7
asl
asl ; *4
clc
adc #<(ftypstr-4)
tax
lda #>(ftypstr-4)
adc #0
ldy #3
jsr putstr
ldx #32
lda ftype
bmi closed$
ldx #"*"
closed$
txa
jsr CHROUT
lda #34
jsr CHROUT
ldx #<fname
lda #>fname
ldy fnameln
jsr putstr
lda #34
jsr CHROUT
ldy fnameln
tasaa$ lda #" "
jsr CHROUT
iny
cpy #17
bne tasaa$
jsr prns
dc.b 18,"Y",146," ",18,"N",146," ",18,"Q",146," ?", 0
ack$ jsr getkey
bcs ack$
cmp #"Y"
beq this$
cmp #3
beq quit$
cmp #"Q"
beq quit$
cmp #"N"
bne ack$
jsr OK_KEY
jmp dirloop$
quit$ jsr CLRCHN
jsr OK_KEY
lda #0
sta ftrack
jmp gotit$
this$ jsr OK_KEY
ldy #0
cp$ lda fname,y
sta inFile,y
iny
cpy fnameln
bne cp$
sty inLen
jmp gotit$
#endif /* V20 */
askdrive:
sta chan$+1
jsr prns
dc.b " DRIVE? ",18,"8",146,"-",18,"9",146,",1",18,"0",146,"-1",18,"7",146,0
ask$ jsr getkey
bcs ask$
cmp #"0"
bcc ask$ ; smaller than "0"
cmp #":"
bcs ask$ ; ":" or greater
sec
sbc #"0"
cmp #8
bcs ook$
;clc
adc #10 ; 0..7 becomes 10..17, 8..9 stays 8..9
ook$ sta drive$+1
jsr putval
jsr CR
lda #0
jsr SETNAM
chan$ lda #15
drive$ ldx #8
ldy #15 ; open chan,drive,15
jsr SETLFS
jsr OPEN
lda chan$+1
jsr CLOSE
lda ST ; READST
;cmp #0
bne nok$
jsr OPEN ; reopen
lda drive$+1
rts
nok$ lda #0
rts
OK_KEY jsr CHROUT
CR lda #13
jmp CHROUT
#if MACH == 64 || MACH == 128
#if CUSTOM == 0
BREAD sty y$+1
ldx #$c0 ; 1581 BURST: LEXS000N L=logical t&s
lda fdos
cmp #"A"
bne 2$
; 1541/1571/4040-format disks
ldx #$40 ; 1571 BURST: TEBS000N T=no transfer
2$ stx cmdline+2
LDA inTrack
STA cmdline+3
LDA inSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #6
STA cmdlen
ldx #14
JSR sendcmd
SEI
BIT D1ICR
LDA D2PRA
EOR #CLKOUT
STA D2PRA
1$ LDA #8
w1$ BIT D1ICR
BEQ w1$
LDA D1SDR
STA status
and #15
cmp #11 ; disk changed -> no data
beq 5$
LDA D2PRA
EOR #CLKOUT
STA D2PRA
ldy #0
3$ LDA #8
4$ BIT D1ICR
BEQ 4$
LDA D2PRA
EOR #CLKOUT
STA D2PRA
LDA D1SDR
sta inBuf,y
sta $d020
INY
BNE 3$
5$ cli
y$ ldy #0
RTS
BSAVE lda d64mode
cmp #8
bne d6471$
lda #$82
dc.b $2c
d6471$ LDA #$02 ; logical write: $82 for 1581, $02 for 157x
STA cmdline+2
LDA oTrack
STA cmdline+3
LDA oSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #$06
STA cmdlen
ldx #15
JSR sendcmd
LDA #$40
STA oldclk$+1
LDY #0
SEI
1$ SEC
JSR SPIN_OUT
2$ LDA D2PRA
oldclk$ EOR #0
AND #$40
BEQ 2$ ; wait for a change in clock
LDA (bTmp),Y
STA D1SDR ; immediately send the next byte
sta $d020
LDA oldclk$+1
EOR #$40
STA oldclk$+1
LDA #8
4$ BIT D1ICR
BEQ 4$ ; wait until it has been sent
INY
BNE 2$
CLC
JSR SPIN_OUT
BIT D1ICR
LDA D2PRA ; clk lo
ORA #$10
STA D2PRA
LDA #8
w1$ BIT D1ICR
BEQ w1$ ; wait for a fast byte
LDA D1SDR
STA status
LDA D2PRA ; clk hi
AND #$EF
STA D2PRA
CLI
RTS
BERR pha
txa
pha
lda #"E"
jsr CHROUT
lda status
jsr puthex
lda #","
jsr CHROUT
lda status
and #15
tay
lda ePtrLo,y
sta str$+1
lda ePtrHi,y
sta str$+2
ldy #0
str$ lda $aaaa,y
beq end$
jsr CHROUT
iny
bne str$
end$
lda #","
jsr CHROUT
lda #"$"
jsr CHROUT
pla
jsr puthex
lda #","
jsr CHROUT
lda #"$"
jsr CHROUT
pla
jsr puthex
lda #13
jmp CHROUT
e0 dc.b "OK",0
e1 dc.b "SELECTED PARTITION",0
e2 dc.b "NO SECTOR",0
e3 dc.b "NO SYNC",0
e4 dc.b "NO DATA BLOCK",0
e5 dc.b "DATA CRC ERROR",0
e6 dc.b "FORMAT ERROR",0
e7 dc.b "VERIFY ERROR",0
e8 dc.b "WRITE PROTECT",0
e9 dc.b "HEADER CRC ERROR",0
e10 dc.b "DATA EXTENDS INTO NEXT BLOCK",0
e11 dc.b "DISK CHANGED",0
e12 dc.b "DISK FORMAT NOT LOGICAL",0
e13 dc.b "DISK CONTROLLER IC ERROR",0
e14 dc.b "SYNTAX ERROR",0
e15 dc.b "NO DISK",0
ePtrLo dc.b <e0,<e1,<e2,<e3,<e4,<e5,<e6,<e7,<e8,<e9,<e10,<e11,<e12,<e13,<e14,<e15
ePtrHi dc.b >e0,>e1,>e2,>e3,>e4,>e5,>e6,>e7,>e8,>e9,>e10,>e11,>e12,>e13,>e14,>e15
; the channel number must be in X
BINQ LDA #$04
STA cmdline+2
LDA #3
STA cmdlen
JSR sendcmd
SEI
BIT D1ICR
LDA D2PRA
EOR #CLKOUT
STA D2PRA
LDA #8
wait1$ BIT D1ICR
BEQ wait1$
LDA D1SDR
STA status
CLI
RTS
cmdline
dc.b "U0", $80, 1, 1, 1, 1, 1, 1
cmdlen
dc.b 0
status
dc.b 0
sendcmd
JSR CHKOUT
LDX #0
LDY cmdlen
1$ LDA cmdline,x
JSR CHROUT
INX
DEY
BNE 1$
jmp CLRCHN
CheckBurst:
stx x$+1
ldx #0
stx FASTSER
#if MACH == 128
jsr LISTEN
lda #$6f
jsr SECOND
lda #"U"
jsr CIOUT
lda #"0"
jsr CIOUT
jsr UNLSN
#else
jsr myLISTEN
lda #$6f
jsr mySECOND
lda #"U"
jsr myCIOUT
lda #"0"
jsr myCIOUT
jsr myUNLSN
#endif
lda #0
bit FASTSER
bvc nob$
x$ ldx #14 ; 1570/1571 seems to need this w/ C64+burst
jsr BINQ
lda #1
nob$ rts
#if MACH == 64
myLISTEN
ora #$20
pha
bit $94 ; C3PO - buffered char flag
bpl 0$
sec
ror $a3 ; set no-ATN flag
jsr myPB ; send buffered char
lsr $94 ; clear buffered char flag
lsr $a3 ; clear no-ATN flag
0$ pla
sta $95 ; set buffered character
sei
jsr ee97 ; DOUT lo, release DATA
#if 0
cmp #$3f
bne 1$
jsr ee85 ; CLKOUT lo, release CLK
#else
lda $dd00
and #$08
bne 1$
jsr SPOUT ; SPOUT
lda #$ff
sta $dc0c
jsr WAITSPIN
txa
ldx #20
2$ dex
bne 2$
tax
#endif
1$ lda $dd00
ora #$08
sta $dd00 ; ATNOUT hi, ATN low
myDEL sei
lda $dd00 ; CLKOUT hi, CLK low
ora #$10
sta $dd00
jsr ee97 ; DOUT lo, release DATA
txa ; DELAY937 delay for 937 cycles
ldx #$b8
0$ dex
bne 0$
tax
myPB sei
jsr ee97 ; DOUT lo, release DATA
jsr eea9 ; wait settle, DATA->C
bcs edad ; device not present
bit $dc0d
jsr ee85 ; CLKOUT lo, release CLK
bit $a3 ; under ATN?
bpl 3$ ;yes->wait for DATA up
; not under ATN, wait for DATA up+down+up
5$ jsr eea9 ; wait settle, DATA->C
bcc 5$ ;wait for DATA released
4$ jsr eea9 ; wait settle, DATA->C
bcs 4$ ;wait for DATA low
#if 0
3$ jsr eea9 ; wait settle, DATA->C
bcc 3$ ;wait for DATA released
#else
3$ lda $dd00
cmp $dd00
bne 3$
pha
lda $dc0d
and #$08
beq 6$
lda #$c0
sta FASTSER
6$ pla
bpl 3$
#endif
lda $dd00 ; CLKOUT hi, CLK low
ora #$10
sta $dd00
lda #$08
sta $a5 ; 8 bits to send
ed66 lda $dd00
cmp $dd00
bne ed66
asl
bcc edaf+1 ;timeout read+write
ror $95 ; next bit to send
bcs ed7a
jsr eea0 ; DOUT hi, DATA low
bne ed7d
ed7a jsr ee97 ; DOUT lo, release DATA
ed7d
jsr ee85 ; CLKOUT lo, release CLK
nop
nop
nop
nop
lda $dd00
and #$df
ora #$10
sta $dd00 ; release DATA, CLK low
dec $a5
bne ed66 ;until 8 bits sent
lda #$04
sta $dc07 ; timer B low byte
lda #$19
sta $dc0f ; force load, one-shot, run timer B
lda $dc0d ; clear old interrupt bits
ed9f lda $dc0d
and #$02 ; timer B expired?
bne edaf+1 ;timeout read+write
jsr eea9 ; wait settle, DATA->C
bcs ed9f ;wait for ACK
cli
rts
edad lda #$80 ; device not present
edaf bit $03a9 ; timeout read+write
ora ST
sta ST
cli
clc
bcc ee03
mySECOND
sta $95
jsr myDEL ; CLKLODELAY
lda $dd00
and #$f7
sta $dd00 ; ATNOUT lo, ATN hi
rts
myCIOUT
bit $94
bmi 0$
sec
ror $94
bne 1$
0$ pha
jsr myPB ; put buffered char
pla
1$ sta $95
clc
rts
myUNLSN
lda #$3f
;pha
;lda FASTSER
;and #$7f
;sta FASTSER
;pla
jsr myLISTEN+2
jmp ee03
SPIN_OUT
bcc SPIN
SPOUT ;lda #$7f
;sta $dc0d
lda #0
sta $dc05
lda #3 ;$04
sta $dc04
lda $dc0e
and #$80
ora #$55
sta $dc0e
bit $dc0d
rts
WAITSPIN
0$ lda $dc0d
and #8
beq 0$
SPIN
lda $dc0e
and #$80 ; preserve TOD mode, SP to input, timer A continuous
ora #1
sta $dc0e
lda #$25 ; Set the normal (PAL) frequence to TimerA
sta $dc04 ; Change if you want to preserve NTSC-rate
lda #$40
sta $dc05
rts
ee97 lda $dd00 ; DOUT lo, release DATA
and #$df
sta $dd00
rts
eea0 lda $dd00 ; DOUT hi, DATA low
ora #$20
sta $dd00
rts
eea9 lda $dd00 ; wait settle, DATA->C
cmp $dd00
bne eea9
asl
rts
ee03 lda $dd00
and #$f7
sta $dd00 ; ATNOUT lo, ATN hi
txa
ldx #$0a
0$ dex
bne 0$
tax
jsr ee85 ; CLKOUT lo, release CLK
jmp ee97 ; DOUT lo, release DATA
ee85 lda $dd00 ; CLKOUT lo, release CLK
and #$ef
sta $dd00
rts
#endif ; MACH == 64
#endif ; CUSTOM == 0
#endif /* V20 */
#if MACH == 64 || MACH == 128
CheckIDE64:
ldy #2
lda $DF09 ; check for Action Replay!
cmp #$78 ; SEI
beq 1$ ; could be AR, must not read $DExx!
0$ lda $DE60,y
cmp IDEID,y
bne 1$
dey
bpl 0$
lda #<inBuf
sta IDE64BR+0
lda #>inBuf
sta IDE64BR+1
1$ sty IDE64present ; negative means IDE64 present
rts
IDEID dc.b "IDE"
#endif
#if MACH != 20 && MACH != 16
d64mode dc.b 0 ; 0 = file, 4 = D64 / D71, 8 = D81, $84 = one drive
d64chan dc.b "#"
first dc.b 0
#endif /* V20 */
mode dc.b 0
overwritemode
dc.b 0
gzip dc.b 0
flags dc.b 0, 0
method dc.b 0, 0
inDrive dc.b 8
outDrive:
dc.b 8
#if !(MACH == 64 || MACH == 128)
be dc.b 0 ; buffer index
#endif
inLen dc.b 8
#if MACH != 20 && MACH != 16
inTrack dc.b 0
inSector dc.b 0
#endif /* V20 */
border ; Order of the bit length code lengths
dc.b 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
cplens_3 ; Copy lengths for literal codes 257..285 - 3
dc.b 3-3, 4-3, 5-3, 6-3, 7-3, 8-3, 9-3, 10-3
dc.b 11-3, 13-3, 15-3, 17-3, 19-3, 23-3, 27-3, 31-3
dc.b 35-3, 43-3, 51-3, 59-3, 67-3, 83-3, 99-3, 115-3
dc.b 131-3, 163-3, 195-3, 227-3, 258-3 ;, 0, 0
cpdistLo ; Copy offsets for distance codes 0..29
dc.b $01, $02, $03, $04, $05, $07, $09, $0d
dc.b $11, $19, $21, $31, $41, $61, $81, $c1
dc.b $01, $81, $01, $01, $01, $01, $01, $01
dc.b $01, $01, $01, $01, $01, $01
cpdistHi ; Copy offsets for distance codes 0..29
dc.b $00, $00, $00, $00, $00, $00, $00, $00
dc.b $00, $00, $00, $00, $00, $00, $00, $00
dc.b $01, $01, $02, $03, $04, $06, $08, $0c
dc.b $10, $18, $20, $30, $40, $60
cplext ; Extra bits for literal codes 257..285
dc.b 0, 0, 0, 0, 0, 0, 0, 0
dc.b 1, 1, 1, 1, 2, 2, 2, 2
dc.b 3, 3, 3, 3, 4, 4, 4, 4
dc.b 5, 5, 5, 5, 0 ;, 99, 99
cpdext ; Extra bits for distance codes
dc.b 0, 0, 0, 0, 1, 1, 2, 2
dc.b 3, 3, 4, 4, 5, 5, 6, 6
dc.b 7, 7, 8, 8, 9, 9, 10, 10
dc.b 11, 11, 12, 12, 13, 13
#if MACH != 20 && MACH != 16
bitReverse:
dc.b $00, $80, $40, $c0, $20, $a0, $60, $e0
dc.b $10, $90, $50, $d0, $30, $b0, $70, $f0
dc.b $08, $88, $48, $c8, $28, $a8, $68, $e8
dc.b $18, $98, $58, $d8, $38, $b8, $78, $f8
dc.b $04, $84, $44, $c4, $24, $a4, $64, $e4
dc.b $14, $94, $54, $d4, $34, $b4, $74, $f4
dc.b $0c, $8c, $4c, $cc, $2c, $ac, $6c, $ec
dc.b $1c, $9c, $5c, $dc, $3c, $bc, $7c, $fc
dc.b $02, $82, $42, $c2, $22, $a2, $62, $e2
dc.b $12, $92, $52, $d2, $32, $b2, $72, $f2
dc.b $0a, $8a, $4a, $ca, $2a, $aa, $6a, $ea
dc.b $1a, $9a, $5a, $da, $3a, $ba, $7a, $fa
dc.b $06, $86, $46, $c6, $26, $a6, $66, $e6
dc.b $16, $96, $56, $d6, $36, $b6, $76, $f6
dc.b $0e, $8e, $4e, $ce, $2e, $ae, $6e, $ee
dc.b $1e, $9e, $5e, $de, $3e, $be, $7e, $fe
dc.b $01, $81, $41, $c1, $21, $a1, $61, $e1
dc.b $11, $91, $51, $d1, $31, $b1, $71, $f1
dc.b $09, $89, $49, $c9, $29, $a9, $69, $e9
dc.b $19, $99, $59, $d9, $39, $b9, $79, $f9
dc.b $05, $85, $45, $c5, $25, $a5, $65, $e5
dc.b $15, $95, $55, $d5, $35, $b5, $75, $f5
dc.b $0d, $8d, $4d, $cd, $2d, $ad, $6d, $ed
dc.b $1d, $9d, $5d, $dd, $3d, $bd, $7d, $fd
dc.b $03, $83, $43, $c3, $23, $a3, $63, $e3
dc.b $13, $93, $53, $d3, $33, $b3, $73, $f3
dc.b $0b, $8b, $4b, $cb, $2b, $ab, $6b, $eb
dc.b $1b, $9b, $5b, $db, $3b, $bb, $7b, $fb
dc.b $07, $87, $47, $c7, $27, $a7, $67, $e7
dc.b $17, $97, $57, $d7, $37, $b7, $77, $f7
dc.b $0f, $8f, $4f, $cf, $2f, $af, $6f, $ef
dc.b $1f, $9f, $5f, $df, $3f, $bf, $7f, $ff
#endif /* V20 */
;============================================================================
; Start of work space - variables
tentimes:
dc.b 0,10,20,30,40,50,60,70,80,90
uncCRC dc.b 0,0,0,0
outSize dc.b 0,0,0,0
compSize
dc.b 0,0,0,0
uncSize
dc.b 0,0,0,0
fileLen dc.b 0
fileDef dc.b "stdout"
errorCode
dc.b 0
errorLen
dc.b 0
zfileLen
dc.b 0,0
zextraLen
dc.b 0,0
#if MACH == 64 || MACH == 128
#if CUSTOM == 0
outBurst
dc.b 0
inBurst
dc.b 0
#endif
inMode
dc.b 0
#endif /* V20 */
#if MACH == 64 || MACH == 128
IDE64present
dc.b 0
#endif
inFile
ds.b 30+4
errorStr
ds.b 56+4
fileName
ds.b 40+4
;inFile = $334
;errorStr = $334+30
;fileName = $334+30+56
Places dc.w 0
fpos dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
ferr dc.b 0
numval dc.w 0
len dc.b 0
literalCodes:
dc.b 0,0
distCodes:
dc.b 0
N:
codelens:
ds.b 320 ; 288+32
;--------------- Space for the Huffman trees ---------------------
#if MACH == 64
S:
literalTree: ; Note: has to be in lower half of the memory
ds.b 256*4
#endif
SPtrLo:
impLengthTree: ; Note: has to be in lower half of the memory
ds.b 32*4 ; 256+32 for Deflate
#if MACH != 20 && MACH != 16
ds.b 32*4 ; 32 extra for Implode
#endif
SPtrHi:
distanceTree: ; Note: has to be in lower half of the memory
#if MACH != 20 && MACH != 16
ds.b 32*4
ds.b 32*4 ; 32 extra for Implode
#else
vic20init:
ldx #0 ; create the CRC32 table (makecrc.c)
crc$ lda #0
sta CRC+3
sta CRC+2
sta CRC+1
stx CRC+0
ldy #8
1$ lsr CRC+3
ror CRC+2
ror CRC+1
ror CRC+0
bcc 0$
lda #$ed
eor CRC+3
sta CRC+3
lda #$b8
eor CRC+2
sta CRC+2
lda #$83
eor CRC+1
sta CRC+1
lda #$20
eor CRC+0
sta CRC+0
0$ dey
bne 1$
lda CRC+0
sta crc32_tab0,x
lda CRC+1
sta crc32_tab1,x
lda CRC+2
sta crc32_tab2,x
lda CRC+3
sta crc32_tab3,x
inx
bne crc$
ldy #0 ; create bitReverse table
lda #0
sta zp0
beq 5$
3$ lda #$80
sta zp1
4$ lda zp0
eor zp1
sta zp0
and zp1
bne 5$
lsr zp1 ; carry to next bit
bne 4$
5$ lda zp0
sta bitReverse,y
iny
bne 3$
rts
.org distanceTree+32*4-1
dc.b 0
#endif /* V20 */
#if . > PROGEND
#err program size overrun
#endif
Booting from UART....done
Flash erase...done
Flash write...done
Flash verify...passed
Booting from flash...done
Reading gzipped stream..done
Magic number mismatch 0x8b95
Booting from flash...done
Reading gzipped stream..done
Last Block: Dynamic Huffman codes
11 table entries used
0x000 - link: 0x001 link: 0x003
0x001 - value: 0x008 link: 0x002
0x002 - value: 0x000 value: 0x004
0x003 - link: 0x00a link: 0x004
0x004 - link: 0x009 link: 0x005
0x005 - value: 0x00a link: 0x006
0x006 - value: 0x010 link: 0x007
0x007 - value: 0x011 link: 0x008
0x008 - value: 0x003 value: 0x012
0x009 - value: 0x005 value: 0x007
0x00a - value: 0x006 value: 0x009
99 table entries used
22 table entries used
CRC: cf2855c7 cf2855c7
Size: 00000fdc 00000fdc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#include "crc32.h"
#include "inflate.h"
#include "libsys.h"
#include "irq.h"
char buffer[4*16384];
char * volatile pPtr_r;
char * volatile pPtr_w;
volatile int timeout_cnt;
volatile int file_len;
void handler3(void)
{
volatile char *pUART_stat = (char*)sys_uart_stat;
volatile char *pUART_data = (char*)sys_uart_data;
while((0x10 & *pUART_stat))
{
// sputs("w: "); print_word((int)pPtr_w); sputs("\n");
if (pPtr_w == &buffer[sizeof(buffer)-1])
pPtr_w = buffer;
*(pPtr_w++) = *pUART_data;
timeout_cnt = 100;
file_len++;
}
}
int READBYTE(z_stream *zs) {
if (zs->avail_in <= 0)
return -1;
zs->avail_in --;
return *(zs->next_in ++);
}
int main(int argc, char **argv)
{
FILE *infp;
int i, gpflags, tmp[4];
unsigned long size, crc;
unsigned char *fileData, *outData;
unsigned long bytes, InflatedSize, InflatedCRC, speed_count;
z_stream zs, zs_speed;
time_t start_time;
fprintf(stderr, "Reading gzipped stream..");
pPtr_r = buffer;
pPtr_w = buffer;
interrupt_register(3, handler3);
interrupt_enable(3);
file_len = 0;
timeout_cnt = 1000000;
while(timeout_cnt--)
{
sleep(1);
}
fprintf(stderr, "done\n");
bytes = file_len;
fileData = pPtr_r;
outData = malloc(65535);
zs.next_in = fileData;
zs.avail_in = (unsigned int) bytes;
zs.next_out = outData;
zs.avail_out = 65535;
tmp[0] = READBYTE(&zs);
if (tmp[0] == -1)
{
// error reading from file
fprintf(stderr, "error reading data from file\n");
return 0;
}
tmp[1] = READBYTE(&zs);
if (tmp[0] != 0x1f || tmp[1] != 0x8b) {
fprintf(stderr, "Magic number mismatch 0x%02x%02x\n",
tmp[0], tmp[1]);
return 20;
}
tmp[0] = READBYTE(&zs);
if(tmp[0] != 8) {
fprintf(stderr, "Unknown compression method: 0x%02x\n", tmp[0]);
return 20;
}
gpflags = READBYTE(&zs);
if ((gpflags & ~0x1f)) {
fprintf(stderr, "Unknown flags set!\n");
}
/* Skip file modification time (4 bytes) */
READBYTE(&zs);
READBYTE(&zs);
READBYTE(&zs);
READBYTE(&zs);
/* Skip extra flags and operating system fields (2 bytes) */
READBYTE(&zs);
READBYTE(&zs);
if ((gpflags & 4)) {
/* Skip extra field */
tmp[0] = READBYTE(&zs);
tmp[1] = READBYTE(&zs);
i = tmp[0] + 256*tmp[1];
while (i--)
{
READBYTE(&zs);
}
}
if((gpflags & 8)) {
while((READBYTE(&zs))) {
}
}
if((gpflags & 16)) {
while((READBYTE(&zs))) {
}
}
if((gpflags & 2)) {
/* Skip CRC16 */
READBYTE(&zs);
READBYTE(&zs);
}
// normal test
if (InflateData(&zs))
{
fprintf(stderr, "Problem during decompression!\n");
return 0;
}
/*
// speed test
fprintf(stderr, "SPEED TEST!\n");
time(&start_time);
speed_count = 0;
while (time(NULL) - start_time < 20)
{
zs_speed.next_in = zs.next_in;
zs_speed.next_out = zs.next_out;
zs_speed.avail_in = zs.avail_in;
zs_speed.avail_out = zs.avail_out;
if (InflateData(&zs_speed))
{
fprintf(stderr, "Problem during decompression!\n");
return 0;
}
speed_count ++;
}
fprintf(stderr, "speed count %ld\n", speed_count);
zs.next_in = zs_speed.next_in;
zs.next_out = zs_speed.next_out;
zs.avail_in = zs_speed.avail_in;
zs.avail_out = zs_speed.avail_out;
*/
crc = READBYTE(&zs);
crc |= (READBYTE(&zs)<<8);
crc |= (READBYTE(&zs)<<16);
crc |= (READBYTE(&zs)<<24);
size = READBYTE(&zs);
size |= (READBYTE(&zs)<<8);
size |= (READBYTE(&zs)<<16);
size |= (READBYTE(&zs)<<24);
InflatedSize = 65535 - zs.avail_out;
InflatedCRC = MakeCRC32(outData, InflatedSize, 0);
fprintf(stderr, "CRC: %08lx %08lx %s\n", crc, InflatedCRC,
(crc != InflatedCRC)?"**error**":"");
fprintf(stderr, "Size: %08lx %08lx %s\n", size, InflatedSize,
(size != InflatedSize)?"**error**":"");
fwrite(outData, 1, zs.avail_out, stdout);
return 0;
}
Booting from flash...done
Reading gzipped stream..done
Not Last Block: Dynamic Huffman codes
12 table entries used
0x000 - link: 0x005 link: 0x001
0x001 - link: 0x002 link: 0x007
0x002 - link: 0x003 link: 0x004
0x003 - value: 0x000 value: 0x004
0x004 - value: 0x005 value: 0x006
0x005 - value: 0x007 link: 0x006
0x006 - value: 0x008 value: 0x009
0x007 - link: 0x008 link: 0x009
0x008 - value: 0x00a value: 0x00b
0x009 - value: 0x00c link: 0x00a
0x00a - value: 0x010 link: 0x00b
0x00b - value: 0x011 value: 0x012
115 table entries used
26 table entries used
Last Block: Dynamic Huffman codes
15 table entries used
0x000 - link: 0x00c link: 0x001
0x001 - link: 0x00a link: 0x002
0x002 - link: 0x008 link: 0x003
0x003 - link: 0x00e link: 0x004
0x004 - link: 0x007 link: 0x005
0x005 - value: 0x012 link: 0x006
0x006 - value: 0x000 value: 0x011
0x007 - value: 0x003 value: 0x00d
0x008 - value: 0x00c link: 0x009
0x009 - value: 0x004 value: 0x00b
0x00a - value: 0x00a link: 0x00b
0x00b - value: 0x005 value: 0x006
0x00c - value: 0x008 link: 0x00d
0x00d - value: 0x007 value: 0x009
0x00e - value: 0x00e value: 0x010
124 table entries used
29 table entries used
CRC: 5af05f03 5af05f03
Size: 00014623 00014623
; todo) detect zero-byte files/directories and skip
; DASM V2.12.04 source
; 1581 1541/71
; 02 can't find header block sector not found
; 03 no address mark detected no sync
; 04 data block not present data block not found
; 05 CRC error in data block data block checksum error
; 06 format error format error
; 07 verify error verify error
; 08 write to a write-protected disk write protect error
; 09 CRC error in header block header block checksum error
; 0a <reserved> data extends into next block
; 0b disk changed / disk ID mismatch disk ID mismatch / disk change
; 0c disk format not logical
; 0d floppy disk controller IC error
; 0e syntax error, invalid job number syntax error
; 0f no disk is present in the drive no drive present
; 8:05 D64.gz->file 1581->1581 unzip2.12
; gunzip.c64
; D64.gz 97275->174848
; 7:54 D64.gz->file 1581->1581 standard file I/O
; 9:00 D64.gz->file 1541->1581 standard file I/O
; 9:46 D64.gz->disk 1581->1541 custom sector write
; 10min D64.gz->disk 1541->1541 one drive custom read/write
; gunzip-std.c64
; D64.gz 97275->174848
; 4:24 D64.gz (skip) 1581->N/A standard file I/O + no save
; 8:10 D64.gz->file 1581->1581 standard I/O
; 13:30 D64.gz->disk 1581->1541 standard I/O (unzip128: 11 min unzip64: 13:10)
; 6:15 D64.gz->disk 1581->1570 burst I/O
; gunzip.128
; 1:22 D64.gz (skip) 1581->N/A standard I/O + burst read + no save
; 3:47 D64.gz->file 1581->1581 standard I/O + burst read
; 4:20 D64.gz->file 1581->1581 standard I/O
; 10:50 D64.gz->disk 1581->1541 standard I/O + burst read
; 11:25 D64.gz->disk 1581->1541 standard I/O
; 6:16 D64.gz->disk 1581->1570 burst read + burst write
; autoboot.zip->autoboot.prg 44sec (unzip101 took 1:17)
; tested on 1581, 1541-II and 1541 (aka "toaster")
processor 6502
ACPTR = $ffa5
CHKIN = $ffc6
CHKOUT = $ffc9
CHRIN = $ffcf
CHROUT = $ffd2
CIOUT = $ffa8
CLOSE = $ffc3
GETIN = $ffe4
CLALL = $ffe7
CLRCHN = $ffcc
LISTEN = $ffb1
OPEN = $ffc0
SECOND = $ff93
SETLFS = $ffba
SETNAM = $ffbd
TALK = $ffb4
TKSA = $ff96
UNLSN = $ffae
UNTLK = $ffab
;READST = $ffb7
ST = $90
#if MACH == 64 || MACH == 128
IDE64BlockWrite = $DEF1
IDE64BlockRead = $DEF4
IDE64BR = $6e ;$6e $6f
be = $69 ;dc.b 0
#endif
#if MACH != 20
D2PRA = $DD00 ; c128 SERIAL PORT LOCATION
CLKOUT = $10 ; SLOW SERIAL CLOCK OUTPUT BIT MASK
CLKIN = $40 ; SLOW SERIAL CLOCK INPUT BIT MASK
D1ICR = $DC0D ; 6526 cia INTERRUPT CONTROL REGISTER
D1SDR = $DC0C ; 6526 cia SERIAL DATA REGISTER
#endif
;MACH = 64
;CUSTOM = 1 ; custom sector write (~11s/track) instead of U2 (~18s/track)
; + custom read w/ custom write
; =============================== C64 =====================================
#if MACH == 64
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $3100
crc32_tab1 = $3200
crc32_tab2 = $3300
crc32_tab3 = $3400
; $cf00-cfff reserved for REU/ramdos
inBuf = $3000
PROGEND = $3000
buf32k = $3500 ; $3500-$cf00 bytes for the output/history buffer
bufsz = $9a00 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
; We would need $ab00 bytes for 4-pass D64, $8900 for 5 passes
curplace EQU $14 ; $15
bb EQU $2 ; bit bucket
bTmp EQU $f7 ; temporary pointer for functions
; equ $f8
zp0 EQU $f9
zp1 equ $fa
countLo EQU $fb
countHi EQU $fc
offset EQU $fd
; EQU $fe
lengths EQU $9e ; for huffman table creation
; EQU $9f
store EQU $ff ; temporary storage
; Used ZP locations: $02, $14-$15, $6a-$6f, $9e-$9f, $f7-$ff and $69 if in c64/128
FASTSER = $02a3
ORG $0801
DC.B $0b,8,$ef,0 ; '239 SYS2061'
DC.B $9e,$32,$30,$36
DC.B $31,0,0,0
#endif
; =============================== C128 ====================================
#if MACH == 128
; $0b00 Cassette buffer
; $0c00 RS232 Input Buffer
; $0d00 RS232 Output Buffer
; $0e00 System Sprites
; $0f00 System Sprites
; $1300-$17ff unused
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $0b00
crc32_tab1 = $0c00
crc32_tab2 = $0d00
crc32_tab3 = $0e00
inBuf = $0f00
;bitReverse = $0d00
PROGEND = $3e00
buf32k = $3e00 ; $3e00-$c000
bufsz = $8200 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
; We would need $ab00 bytes for 4-pass D64, $8900 for 5 passes
S = $1300
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
curplace EQU $86 ; $87
bb EQU $8c ; bit bucket
countLo EQU $88
countHi EQU $89
lengths EQU $8a ; for huffman table creation
; EQU $8b
bTmp EQU $fa ; temporary pointer for functions
; equ $fb
zp0 EQU $fc
zp1 equ $fd
offset EQU $fe
; EQU $ff
store EQU $8d ; temporary storage
prns = $ff7d
SETBANK = $ff68
SPIN_OUT = $FF47 ; sET UP FAST SERIAL FOR INPUT OR OUTPUT.
; sec FOR OUTPUT, clc FOR INPUT.
READBANK = $ff74 ; lda (ZP),y bank in X, ZP in A
WRITEBANK = $ff77 ; sta (ZP),y bank in X, value in A, ZP in $02b9
VERIFYBANK = $ff7a ; cmp (ZP),y bank in X, value in A, ZP in $02c8
FASTSER = $0a1c
ORG $1c01
DC.B $0b,$1c,$ef,0 ; '239 SYS7181'
DC.B $9e,$37,$31,$38
DC.B $31,0,0,0
lda $ff00
pha
lda #$0e ; RAM0, System ROM, RAM, BASIC
sta $ff00
lda #0
sta $f7 ; enable SHIFT-C=
sta $f8
sta $f9
tax
jsr SETBANK ; I/O source/destination RAM0 64k
#endif
; =============================== VIC20 ====================================
#if MACH == 20
; $1201-2000 base memory
; $2000-3fff 8k expansion
; $4000-5fff 8k expansion
; ----
; $6000-7fff 8k expansion
; ----
; $a000-bfff 8k expansion
; $0400-0fff 3k expansion
bitReverse = $2600
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $2700
crc32_tab1 = $2800
crc32_tab2 = $2900
crc32_tab3 = $2a00
inBuf = $2b00
PROGEND = $2600
buf32k = $3000
bufsz = $3000
S = $2c00 ; $2c00..$2fff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
curplace EQU $86 ; $87
bb EQU $8c ; bit bucket
countLo EQU $88
countHi EQU $89
lengths EQU $8a ; for huffman table creation
; EQU $8b
bTmp EQU $fa ; temporary pointer for functions
; equ $fb
zp0 EQU $fc
zp1 equ $fd
offset EQU $fe
; EQU $ff
store EQU $8d ; temporary storage
ORG $1201
DC.B $0b,8,$ef,0 ; '239 SYS4621'
DC.B $9e,$34,$36,$32
DC.B $31,0,0,0
#endif
; =============================== Plus/4 ====================================
#if MACH == 4
; C16 $1000-$3fff +/4 $1000-$fd00
CRC = $d8 ; 8,9,a,b
crc32_tab0 = $3000
crc32_tab1 = $3100
crc32_tab2 = $3200
crc32_tab3 = $3300
inBuf = $3800
PROGEND = $3000
buf32k = $3900 ; $3900..$fd00
bufsz = $c400
S = $3400 ; $3400..$37ff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
; $00D8-00E8 216-232 Area for use by application software
curplace EQU $dc ; $dd
bb EQU $de ; bit bucket
countLo EQU $df
countHi EQU $e0
lengths EQU $e1 ; for huffman table creation
; EQU $e2
bTmp EQU $e3 ; temporary pointer for functions
; equ $e4
zp0 EQU $e5
zp1 equ $e6
offset EQU $e7
; EQU $e8
store EQU $d7 ; temporary storage
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; =============================== C16 ====================================
#if MACH == 16
; C16 $1000-$3fff +/4 $1000-$fd00
bitReverse = $2600
CRC = $d8 ; 8,9,a,b
crc32_tab0 = $2700
crc32_tab1 = $2800
crc32_tab2 = $2900
crc32_tab3 = $2a00
PROGEND = $2600
inBuf = $2b00
buf32k = $3000 ; $3000..$8000
bufsz = $5000 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
S = $2c00 ; $2c00..$2fff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
; $00D8-00E8 216-232 Area for use by application software
curplace EQU $dc ; $dd
bb EQU $de ; bit bucket
countLo EQU $df
countHi EQU $e0
lengths EQU $e1 ; for huffman table creation
; EQU $e2
bTmp EQU $e3 ; temporary pointer for functions
; equ $e4
zp0 EQU $e5
zp1 equ $e6
offset EQU $e7
; EQU $e8
store EQU $d7 ; temporary storage
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; ========================================================================
cli ; in case..!?!?
jsr prns
dc.b 147
#if MACH == 64
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$b0,$ae,$b0,$ae,$ae,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$20,$ab,$ae,$ad,$b3
#endif
#if MACH == 4
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$20,$ae,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7b,$ad,$b3
#endif
#if MACH == 128
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$ae,$b0,$ae,$b0,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$b0,$bd,$ab,$b3
#endif
#if CUSTOM
dc.b "V1.11CUSTOM 19.11.2002",13
#else
dc.b "V1.11 19.11.2002",13
#endif
#if MACH == 64
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$bd,$ad,$bd,$20,$bd
#endif
#if MACH == 4
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$20,$20,$bd
#endif
#if MACH == 128
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$ad,$bd,$ad,$bd
#endif
dc.b " BY PASI'ALBERT'OJALA", 13
dc.b " HTTP://WWW.CS.TUT.FI/%7EALBERT/", 13, 13, 0
#if MACH != 20 && MACH != 16
ldx #0 ; create the CRC32 table (makecrc.c)
crc$ lda #0
sta CRC+3
sta CRC+2
sta CRC+1
stx CRC+0
ldy #8
1$ lsr CRC+3
ror CRC+2
ror CRC+1
ror CRC+0
bcc 0$
lda #$ed
eor CRC+3
sta CRC+3
lda #$b8
eor CRC+2
sta CRC+2
lda #$83
eor CRC+1
sta CRC+1
lda #$20
eor CRC+0
sta CRC+0
0$ dey
bne 1$
lda CRC+0
sta crc32_tab0,x
lda CRC+1
sta crc32_tab1,x
lda CRC+2
sta crc32_tab2,x
lda CRC+3
sta crc32_tab3,x
inx
bne crc$
#else
jsr vic20init
#endif /* V20 */
#if MACH == 64 || MACH == 128
jsr CheckIDE64
#endif
restart lda #0
#if MACH == 64 || MACH == 128
sta inTrack
;sta inSector
sta d64mode
sta first
#endif
sta gzip
idrive$ jsr prns
dc.b "INPUT", 0
lda #14 ; channel #
jsr askdrive
beq idrive$
sta inDrive
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda inDrive
ldx #14
jsr CheckBurst
sta inBurst
#endif
#endif
rfile$ jsr prns
dc.b "INPUT FILE?", 13, 34, 0
lda #0
sta inFile
lda #<inFile
ldx #>inFile
ldy #28 ; max filename length
jsr getstr
lda #0
sta inFile,y
sty inLen
lda #34
jsr OK_KEY
#if MACH != 20 && MACH != 16
jsr ReadDir
lda inLen
beq rfile$
;lda inTrack ; allow non-existing files
;beq rfile$
#endif /* V20 */
odrive$ jsr prns
dc.b "OUTPUT", 0
lda #15
jsr askdrive
beq odrive$
sta outDrive
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda outDrive
ldx #15
jsr CheckBurst
sta outBurst
#endif
#endif
#if CUSTOM == 1
lda outDrive
cmp inDrive
bne oneortwo$
lda fdos
cmp #"A"
bne oneortwo$ ; not a 1541-format disk
lda inTrack
beq oneortwo$ ; we did not find the file from the directory
jsr prns
dc.b "DISSOLVE D64 TO 1541/71 DRIVE ",18,"Y",146,"/",18,"N",146," ? ", 0
onedrive$
jsr getkey
cmp #"N"
beq oneortwo0$
cmp #"Y"
bne onedrive$
jsr OK_KEY
; okay, one drive and D64, set d64mode = $84
lda #$84
sta d64mode ; one-drive mode: custom read and write
jsr initwriter
jmp 2$
oneortwo0$
jsr OK_KEY
; Open input file
oneortwo$
lda #0
sta inMode
#endif
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda inBurst
beq openin$ ; can't use burst read -> use sequential read
lda inTrack
bne 2$ ; start t&s known, use burst read
#endif
#endif
openin$ ldx #<inFile
ldy #>inFile
lda inLen
jsr SETNAM
lda #2
ldx inDrive
ldy #0 ; open 2,8,0,"fileName"
jsr SETLFS
jsr OPEN
#if MACH == 64 || MACH == 128
inc inMode
#endif /* V20 */
ldx #14
jsr geterror
cmp #0
beq 2$
jsr CLALL
jsr CLRCHN
ldx #<errorSt24..127
jsr GetBit
rol ; 48..255
cmp #200
bcc 48199$
; 200..255
;sec
sbc #128 ; 72..127
jsr GetBit
rol ; 144..255
0$ jsr PutBuffer ; 0..143 & 144..255
jmp Fixed ; continue loop
48199$ ;clc ; 48..199
sbc #47 ; 0..151
cmp #144
bcc 0$
; 144..151
;sec
adc #135 ; 280..287 (24..31)
bcs lz77$
023$ cmp #0 ; 0..23 -> 256..279
bne lz77$
rts ; 256 == EOF
lz77$ jsr GetLen ; 1..23
ldx #5
jsr GetBits ; reverse default bit order
jsr CopyLz
jmp Fixed
GetLen tay ; j
;dey ; 1..23 -> 0..22
sty store
ldx cplext-1,y
jsr READBITS ; 0..5 bits
;clc
adc #3 ; does not overflow
ldy store
adc cplens_3-1,y ; 0..255 may overflow
sta countLo
lda #0
rol ;adc #0
sta countHi
rts
; cpdist-index in A
; offset in "offset"
; length in countLo & countHi
CopyLz sta store
tay
ldx cpdext,y
cpx #9
bcs 913$
jsr READBITS ; 1..8 bits
sta offset+0
lda #0
jmp ov$
913$ stx x$+1
ldx #8 ; 9..13 bits
jsr READBITS
sta offset+0
x$ lda #9
and #7
tax
jsr READBITS
ov$ sta offset+1
ldy store
lda cpdistLo,y
;clc ; READBITS cleared it (either one)
adc offset+0
sta offset+0
lda cpdistHi,y
adc offset+1
sta offset+1
; Entry-point for Implode/Reduce
CopyLz2 lda outCmd+1 ; low-byte of current output position
sec
sbc offset+0
sta offset+0
lda outCmd+2 ; high-byte of current output position
sbc offset+1
bcc buffix$ ; wrapped below 0, must be out of buffer -> fix
cmp #>buf32k
bcs bufok$ ; not below 0 and not below buffer start -> ok
; not below 0 but below buffer start -> fix
buffix$ ;clc ; C is clear in both entries
adc #>bufsz
bufok$ sta offset+1
; change dec;lda;cmp #255;bne -> dec;bne
inc countLo
inc countHi
jmp l3$
l0$
ldy #0
lda (offset),y
jsr PutBuffer
inc offset+0
bne l3$
ldy offset+1
iny
cpy #>(buf32k+bufsz) ; wrap to the start of the (ring)buffer
bne l2$
ldy #>buf32k
l2$ sty offset+1
l3$ dec countLo
bne l0$
dec countHi
bne l0$
rts
Dynamic ldx #5
jsr READBITS
;clc
adc #1
sta literalCodes+0 ; + 257
lda #1
sta literalCodes+1
ldx #5
jsr READBITS
;clc
adc #1
sta distCodes ; + 1
ldx #4
jsr READBITS
;clc
adc #4
sta countLo
lda #0
sta countHi
;lda #0
ldx #19
0$ sta codelens,x
dex
bpl 0$
1$ ldx #3
jsr READBITS
ldy countHi
ldx border,y
sta codelens,x
inc countHi
dec countLo
bne 1$
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<distanceTree
sta Places+0
lda #>distanceTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy #0
lda #19
jsr CreateTree
beq tok1$
; invalid tree
rts
;
tok1$ lda literalCodes+0
clc
adc distCodes
sta countLo
lda literalCodes+1
adc #0
sta countHi
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
5$ lda #<distanceTree ; bitlen decode 117 bytes (UnZip 173 bytes)
ldy #>distanceTree
jsr DecodeValue
cmp #16
beq 16$
bcc 015$
; j>16
cmp #17
beq 17$
ldx #7
jsr READBITS
;clc
adc #11
jmp 8$
17$ ldx #3
jsr READBITS
;clc
adc #3
8$ tax
ldy #0
tya ;lda #0
9$ sta (lengths),y
inc lengths+0
bne l0$
inc lengths+1
l0$ dec countLo
bne l1$
dec countHi
l1$ dex
bne 9$
jmp 6$
16$ ; j==16
ldx #2
jsr READBITS
;clc
adc #3
tax
dec lengths+1
ldy #255
7$ lda (lengths),y ; lengths[i-1]
inc lengths+0
bne l2$
inc lengths+1
l2$ sta (lengths),y ; lengths[i]
dec countLo
bne l3$
dec countHi
l3$ dex
bne 7$
inc lengths+1
jmp 6$
015$ ; j<16
ldy #0
sta (lengths),y
inc lengths+0
bne l4$
inc lengths+1
l4$ dec countLo
bne 6$
dec countHi
6$ lda countHi
bpl 5$
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<literalTree
sta Places+0
lda #>literalTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta length
inc outSize+1
bne 0$
inc outSize+2
bne 0$
inc outSize+3
0$
#if MACH == 20
ldy outCmd+2
bpl outCmd ; ok, less than $8000
; move $8000..9fff -> $a000..bfff
pha
tya
ora #$20
sta outCmd+2
pla
#endif
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
outCmd sta $aaaa
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 20
sty outCmd+2 ; restore "real" address
#endif
; updcrc()
; (crc32_tab[((int)crc ^ cp) & 255] ^ (crc >> 8))
eor CRC+0 ; 3
tay ; 2
lda crc32_tab0,y ; 4
eor CRC+1 ; 3
sta CRC+0 ; 3
lda crc32_tab1,y ; 4
eor CRC+2 ; 3
sta CRC+1 ; 3
lda crc32_tab2,y ; 4
eor CRC+3 ; 3
sta CRC+2 ; 3
lda crc32_tab3,y ; 4
sta CRC+3 ; 3 =42 cycles/byte = ~7.5 secs for 170.75kB
inc outCmd+1 ;6
bne 2$ ;2/3
inc outCmd+2
lda outCmd+2
cmp #>(buf32k+bufsz)
bne 2$
; Save buffer data buffer32k .. (outCmd)
jsr FlushBuffer
jsr InitBuffer32k
2$
puty ldy #0 ; restore Y value
rts
InitBuffer32k:
; Init buffer pointer
lda #<buf32k
sta outCmd+1
lda #>buf32k
sta outCmd+2
rts
#if MACH != 20 && MACH != 16
; Implode expects a cleared buffer
ClearBuffer:
lda #<buf32k
sta 0$+1
lda #>buf32k
sta 0$+2
lda #0
tay
0$ sta $aa00,y
iny
bne 0$
inc 0$+2
ldx 0$+2
cpx #>(buf32k+bufsz)
bne 0$
rts
#endif /* V20 */
FlushBuffer: ; Can trash A & Y, X
lda mode
cmp #"N" ; skip it
bne do$
rts
do$
#if MACH != 20 && MACH != 16
#if CUSTOM
lda d64mode
bpl donow$
jsr prns
dc.b "INSERT DESTINATION DISK & PRESS ",18,"D",146," ", 0
wait$ jsr getkey
cmp #"D"
bne wait$
jsr OK_KEY
donow$
#endif
jsr onoff
lda d64mode
beq no$
jsr writebuf
jsr CLRCHN
jsr onoff
#if CUSTOM
lda d64mode
bmi ask$
rts
ask$ jsr prns
dc.b "INSERT SOURCE DISK & PRESS ",18,"S",146," ", 0
wait2$ jsr getkey
cmp #"S"
bne wait2$
jmp OK_KEY
#else
rts
#endif
#endif /* V20 */
no$ ldx #3
jsr CHKOUT ; (sends LISTEN+SECOND)
lda #<buf32k
sta bTmp+0
lda #>buf32k
sta bTmp+1
1$
#if MACH == 64 || MACH == 128
lda IDE64present
bpl noIDE64here$ ; IDE64 not found
lda outCmd+1
sec
sbc bTmp+0
tax
lda outCmd+2
sbc bTmp+1
tay
lda #bTmp
inc $d020
jsr IDE64BlockWrite
bcc IDE64writeback$ ;Tried to write to a floppy...
noIDE64here$
#endif
lda bTmp+0
cmp outCmd+1
bne 0$
lda bTmp+1
cmp outCmd+2
bne 0$
IDE64writeback$
jsr CLRCHN
jmp onoff
0$
#if MACH == 20
lda bTmp+1
pha
bpl base$ ; ok, less than $8000
; move $8000..9fff -> $a000..bfff
ora #$20
sta bTmp+1
base$
#endif /* V20 */
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
ldy #0
lda (bTmp),y
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
sta $ff19
jsr CHROUT
#endif
#if MACH == 64 || MACH == 128
sta $d020
jsr CHROUT
#endif
#if MACH == 20
pha
jsr CHROUT
pla
and #7
eor $900f
sta $900f
pla
sta bTmp+1 ; restore "real" address
#endif /* V20 */
inc bTmp+0
bne 1$
inc bTmp+1
jmp 1$
;--------------- Huffman routines ---------------------
;================================================================
;
; struct HufNode
; 0 0-bit value LSB
; 1 0-bit value MSb (D0) + leaf flag (D7)
; 2 1-bit value LSB or jump LO
; 3 1-bit value MSb (D0) + leaf flag (D7) or jump HI (D7=0)
;UnZip: create huffman codes 299 bytes (gunzip 397(new 202) bytes)
IsPat ; Check if there is another code of the current length
; while (1) {
; if (fpos[len] >= fmax)
; return -1;
; if (flens[fpos[len]] == len)
; return fpos[len]++;
; fpos[len]++;
; }
lda len
asl
tax
loop$ ldy fpos+0,x
lda fpos+1,x ; fpos[len]
cmp numval+1
bcc 0$
cpy numval+0
beq not$
0$ cmp #0 ; HI
bne 1$
lda (lengths),y
jmp 2$
1$ inc lengths+1 ; next page
lda (lengths),y
dec lengths+1
2$ cmp len
bne inc$
; got it
lda fpos+1,x
lsr ; shift HI to C
tya ; LO to A
inc fpos+0,x
bne 3$
inc fpos+1,x
3$ ldx #0 ; return zero set (and negative clear)
rts
inldcard(s) 26 bytes
ldy #0
cname$ lda inFile,y
cmp "?"
beq 22$ ; skip one char
cmp "*"
beq gotit$ ; skip rest of name TODO: real *
cmp fname,y
beq 22$
jmp dirloop$
22$ iny
cpy fnameln
bne cname$
#endif
; name matches
gotit$
#if MACH != 20 && MACH != 16
lda ftrack
sta inTrack
lda fsector
sta inSector
#endif /* V20 */
lda #2
jmp CLOSE ; jsr + rts
ask$
#if 0
ldx #">"
lda ftype
and #64
bne locked$
ldx #32
locked$
txa
jsr CHROUT
#endif
lda fblocks+1
jsr puthex
lda fblocks+0
jsr puthex
lda #" "
jsr CHROUT
lda ftype
and #7
asl
asl ; *4
clc
adc #<(ftypstr-4)
tax
lda #>(ftypstr-4)
adc #0
ldy #3
jsr putstr
ldx #32
lda ftype
bmi closed$
ldx #"*"
closed$
txa
jsr CHROUT
lda #34
jsr CHROUT
ldx #<fname
lda #>fname
ldy fnameln
jsr putstr
lda #34
jsr CHROUT
ldy fnameln
tasaa$ lda #" "
jsr CHROUT
iny
cpy #17
bne tasaa$
jsr prns
dc.b 18,"Y",146," ",18,"N",146," ",18,"Q",146," ?", 0
ack$ jsr getkey
bcs ack$
cmp #"Y"
beq this$
cmp #3
beq quit$
cmp #"Q"
beq quit$
cmp #"N"
bne ack$
jsr OK_KEY
jmp dirloop$
quit$ jsr CLRCHN
jsr OK_KEY
lda #0
sta ftrack
jmp gotit$
this$ jsr OK_KEY
ldy #0
cp$ lda fname,y
sta inFile,y
iny
cpy fnameln
bne cp$
sty inLen
jmp gotit$
#endif /* V20 */
askdrive:
sta chan$+1
jsr prns
dc.b " DRIVE? ",18,"8",146,"-",18,"9",146,",1",18,"0",146,"-1",18,"7",146,0
ask$ jsr getkey
bcs ask$
cmp #"0"
bcc ask$ ; smaller than "0"
cmp #":"
bcs ask$ ; ":" or greater
sec
sbc #"0"
cmp #8
bcs ook$
;clc
adc #10 ; 0..7 becomes 10..17, 8..9 stays 8..9
ook$ sta drive$+1
jsr putval
jsr CR
lda #0
jsr SETNAM
chan$ lda #15
drive$ ldx #8
ldy #15 ; open chan,drive,15
jsr SETLFS
jsr OPEN
lda chan$+1
jsr CLOSE
lda ST ; READST
;cmp #0
bne nok$
jsr OPEN ; reopen
lda drive$+1
rts
nok$ lda #0
rts
OK_KEY jsr CHROUT
CR lda #13
jmp CHROUT
#if MACH == 64 || MACH == 128
#if CUSTOM == 0
BREAD sty y$+1
ldx #$c0 ; 1581 BURST: LEXS000N L=logical t&s
lda fdos
cmp #"A"
bne 2$
; 1541/1571/4040-format disks
ldx #$40 ; 1571 BURST: TEBS000N T=no transfer
2$ stx cmdline+2
LDA inTrack
STA cmdline+3
LDA inSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #6
STA cmdlen
ldx #14
JSR sendcmd
SEI
BIT D1ICR
LDA D2PRA
EOR #CLKOUT
STA D2PRA
1$ LDA #8
w1$ BIT D1ICR
BEQ w1$
LDA D1SDR
STA status
and #15
cmp #11 ; disk changed -> no data
beq 5$
LDA D2PRA
EOR #CLKOUT
STA D2PRA
ldy #0
3$ LDA #8
4$ BIT D1ICR
BEQ 4$
LDA D2PRA
EOR #CLKOUT
STA D2PRA
LDA D1SDR
sta inBuf,y
sta $d020
INY
BNE 3$
5$ cli
y$ ldy #0
RTS
BSAVE lda d64mode
cmp #8
bne d6471$
lda #$82
dc.b $2c
d6471$ LDA #$02 ; logical write: $82 for 1581, $02 for 157x
STA cmdline+2
LDA oTrack
STA cmdline+3
LDA oSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #$06
STA cmdlen
ldx #15
JSR sendcmd
LDA #$40
STA oldclk$+1
LDY #0
SEI
1$ SEC
JSR SPIN_OUT
2$ LDA D2PRA
oldclk$ EOR #0
AND #$40
BEQ 2$ ; wait for a change in clock
LDA (bTmp),Y
STA D1SDR ; immediately send the next byte
sta $d020
LDA oldclk$+1
EOR #$40
STA oldclk$+1
LDA #8
4$ BIT D1ICR
BEQ 4$ ; wait until it has been sent
INY
BNE 2$
CLC
JSR SPIN_OUT
BIT D1ICR
LDA D2PRA ; clk lo
ORA #$10
STA D2PRA
LDA #8
w1$ BIT D1ICR
BEQ w1$ ; wait for a fast byte
LDA D1SDR
STA status
LDA D2PRA ; clk hi
AND #$EF
STA D2PRA
CLI
RTS
BERR pha
txa
pha
lda #"E"
jsr CHROUT
lda status
jsr puthex
lda #","
jsr CHROUT
lda status
and #15
tay
lda ePtrLo,y
sta str$+1
lda ePtrHi,y
sta str$+2
ldy #0
str$ lda $aaaa,y
beq end$
jsr CHROUT
iny
bne str$
end$
lda #","
jsr CHROUT
lda #"$"
jsr CHROUT
pla
jsr puthex
lda #","
jsr CHROUT
lda #"$"
jsr CHROUT
pla
jsr puthex
lda #13
jmp CHROUT
e0 dc.b
Booting from UART....done
Flash erase...done
Flash write...done
Flash verify...passed
Booting from flash...done
Reading gzipped stream..done
Not Last Block: Dynamic Huffman codes
12 table entries used
0x000 - link: 0x005 link: 0x001
0x001 - link: 0x002 link: 0x007
0x002 - link: 0x003 link: 0x004
0x003 - value: 0x000 value: 0x004
0x004 - value: 0x005 value: 0x006
0x005 - value: 0x007 link: 0x006
0x006 - value: 0x008 value: 0x009
0x007 - link: 0x008 link: 0x009
0x008 - value: 0x00a value: 0x00b
0x009 - value: 0x00c link: 0x00a
0x00a - value: 0x010 link: 0x00b
0x00b - value: 0x011 value: 0x012
115 table entries used
26 table entries used
Last Block: Dynamic Huffman codes
15 table entries used
0x000 - link: 0x00c link: 0x001
0x001 - link: 0x00a link: 0x002
0x002 - link: 0x008 link: 0x003
0x003 - link: 0x00e link: 0x004
0x004 - link: 0x007 link: 0x005
0x005 - value: 0x012 link: 0x006
0x006 - value: 0x000 value: 0x011
0x007 - value: 0x003 value: 0x00d
0x008 - value: 0x00c link: 0x009
0x009 - value: 0x004 value: 0x00b
0x00a - value: 0x00a link: 0x00b
0x00b - value: 0x005 value: 0x006
0x00c - value: 0x008 link: 0x00d
0x00d - value: 0x007 value: 0x009
0x00e - value: 0x00e value: 0x010
124 table entries used
29 table entries used
CRC: 5af05f03 5af05f03
Size: 00014623 00014623
; todo) detect zero-byte files/directories and skip
; DASM V2.12.04 source
; 1581 1541/71
; 02 can't find header block sector not found
; 03 no address mark detected no sync
; 04 data block not present data block not found
; 05 CRC error in data block data block checksum error
; 06 format error format error
; 07 verify error verify error
; 08 write to a write-protected disk write protect error
; 09 CRC error in header block header block checksum error
; 0a <reserved> data extends into next block
; 0b disk changed / disk ID mismatch disk ID mismatch / disk change
; 0c disk format not logical
; 0d floppy disk controller IC error
; 0e syntax error, invalid job number syntax error
; 0f no disk is present in the drive no drive present
; 8:05 D64.gz->file 1581->1581 unzip2.12
; gunzip.c64
; D64.gz 97275->174848
; 7:54 D64.gz->file 1581->1581 standard file I/O
; 9:00 D64.gz->file 1541->1581 standard file I/O
; 9:46 D64.gz->disk 1581->1541 custom sector write
; 10min D64.gz->disk 1541->1541 one drive custom read/write
; gunzip-std.c64
; D64.gz 97275->174848
; 4:24 D64.gz (skip) 1581->N/A standard file I/O + no save
; 8:10 D64.gz->file 1581->1581 standard I/O
; 13:30 D64.gz->disk 1581->1541 standard I/O (unzip128: 11 min unzip64: 13:10)
; 6:15 D64.gz->disk 1581->1570 burst I/O
; gunzip.128
; 1:22 D64.gz (skip) 1581->N/A standard I/O + burst read + no save
; 3:47 D64.gz->file 1581->1581 standard I/O + burst read
; 4:20 D64.gz->file 1581->1581 standard I/O
; 10:50 D64.gz->disk 1581->1541 standard I/O + burst read
; 11:25 D64.gz->disk 1581->1541 standard I/O
; 6:16 D64.gz->disk 1581->1570 burst read + burst write
; autoboot.zip->autoboot.prg 44sec (unzip101 took 1:17)
; tested on 1581, 1541-II and 1541 (aka "toaster")
processor 6502
ACPTR = $ffa5
CHKIN = $ffc6
CHKOUT = $ffc9
CHRIN = $ffcf
CHROUT = $ffd2
CIOUT = $ffa8
CLOSE = $ffc3
GETIN = $ffe4
CLALL = $ffe7
CLRCHN = $ffcc
LISTEN = $ffb1
OPEN = $ffc0
SECOND = $ff93
SETLFS = $ffba
SETNAM = $ffbd
TALK = $ffb4
TKSA = $ff96
UNLSN = $ffae
UNTLK = $ffab
;READST = $ffb7
ST = $90
#if MACH == 64 || MACH == 128
IDE64BlockWrite = $DEF1
IDE64BlockRead = $DEF4
IDE64BR = $6e ;$6e $6f
be = $69 ;dc.b 0
#endif
#if MACH != 20
D2PRA = $DD00 ; c128 SERIAL PORT LOCATION
CLKOUT = $10 ; SLOW SERIAL CLOCK OUTPUT BIT MASK
CLKIN = $40 ; SLOW SERIAL CLOCK INPUT BIT MASK
D1ICR = $DC0D ; 6526 cia INTERRUPT CONTROL REGISTER
D1SDR = $DC0C ; 6526 cia SERIAL DATA REGISTER
#endif
;MACH = 64
;CUSTOM = 1 ; custom sector write (~11s/track) instead of U2 (~18s/track)
; + custom read w/ custom write
; =============================== C64 =====================================
#if MACH == 64
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $3100
crc32_tab1 = $3200
crc32_tab2 = $3300
crc32_tab3 = $3400
; $cf00-cfff reserved for REU/ramdos
inBuf = $3000
PROGEND = $3000
buf32k = $3500 ; $3500-$cf00 bytes for the output/history buffer
bufsz = $9a00 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
; We would need $ab00 bytes for 4-pass D64, $8900 for 5 passes
curplace EQU $14 ; $15
bb EQU $2 ; bit bucket
bTmp EQU $f7 ; temporary pointer for functions
; equ $f8
zp0 EQU $f9
zp1 equ $fa
countLo EQU $fb
countHi EQU $fc
offset EQU $fd
; EQU $fe
lengths EQU $9e ; for huffman table creation
; EQU $9f
store EQU $ff ; temporary storage
; Used ZP locations: $02, $14-$15, $6a-$6f, $9e-$9f, $f7-$ff and $69 if in c64/128
FASTSER = $02a3
ORG $0801
DC.B $0b,8,$ef,0 ; '239 SYS2061'
DC.B $9e,$32,$30,$36
DC.B $31,0,0,0
#endif
; =============================== C128 ====================================
#if MACH == 128
; $0b00 Cassette buffer
; $0c00 RS232 Input Buffer
; $0d00 RS232 Output Buffer
; $0e00 System Sprites
; $0f00 System Sprites
; $1300-$17ff unused
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $0b00
crc32_tab1 = $0c00
crc32_tab2 = $0d00
crc32_tab3 = $0e00
inBuf = $0f00
;bitReverse = $0d00
PROGEND = $3e00
buf32k = $3e00 ; $3e00-$c000
bufsz = $8200 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
; We would need $ab00 bytes for 4-pass D64, $8900 for 5 passes
S = $1300
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
curplace EQU $86 ; $87
bb EQU $8c ; bit bucket
countLo EQU $88
countHi EQU $89
lengths EQU $8a ; for huffman table creation
; EQU $8b
bTmp EQU $fa ; temporary pointer for functions
; equ $fb
zp0 EQU $fc
zp1 equ $fd
offset EQU $fe
; EQU $ff
store EQU $8d ; temporary storage
prns = $ff7d
SETBANK = $ff68
SPIN_OUT = $FF47 ; sET UP FAST SERIAL FOR INPUT OR OUTPUT.
; sec FOR OUTPUT, clc FOR INPUT.
READBANK = $ff74 ; lda (ZP),y bank in X, ZP in A
WRITEBANK = $ff77 ; sta (ZP),y bank in X, value in A, ZP in $02b9
VERIFYBANK = $ff7a ; cmp (ZP),y bank in X, value in A, ZP in $02c8
FASTSER = $0a1c
ORG $1c01
DC.B $0b,$1c,$ef,0 ; '239 SYS7181'
DC.B $9e,$37,$31,$38
DC.B $31,0,0,0
lda $ff00
pha
lda #$0e ; RAM0, System ROM, RAM, BASIC
sta $ff00
lda #0
sta $f7 ; enable SHIFT-C=
sta $f8
sta $f9
tax
jsr SETBANK ; I/O source/destination RAM0 64k
#endif
; =============================== VIC20 ====================================
#if MACH == 20
; $1201-2000 base memory
; $2000-3fff 8k expansion
; $4000-5fff 8k expansion
; ----
; $6000-7fff 8k expansion
; ----
; $a000-bfff 8k expansion
; $0400-0fff 3k expansion
bitReverse = $2600
CRC = $6a ; b,c,d ;dc.b 255,255,255,255
crc32_tab0 = $2700
crc32_tab1 = $2800
crc32_tab2 = $2900
crc32_tab3 = $2a00
inBuf = $2b00
PROGEND = $2600
buf32k = $3000
bufsz = $3000
S = $2c00 ; $2c00..$2fff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
curplace EQU $86 ; $87
bb EQU $8c ; bit bucket
countLo EQU $88
countHi EQU $89
lengths EQU $8a ; for huffman table creation
; EQU $8b
bTmp EQU $fa ; temporary pointer for functions
; equ $fb
zp0 EQU $fc
zp1 equ $fd
offset EQU $fe
; EQU $ff
store EQU $8d ; temporary storage
ORG $1201
DC.B $0b,8,$ef,0 ; '239 SYS4621'
DC.B $9e,$34,$36,$32
DC.B $31,0,0,0
#endif
; =============================== Plus/4 ====================================
#if MACH == 4
; C16 $1000-$3fff +/4 $1000-$fd00
CRC = $d8 ; 8,9,a,b
crc32_tab0 = $3000
crc32_tab1 = $3100
crc32_tab2 = $3200
crc32_tab3 = $3300
inBuf = $3800
PROGEND = $3000
buf32k = $3900 ; $3900..$fd00
bufsz = $c400
S = $3400 ; $3400..$37ff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
; $00D8-00E8 216-232 Area for use by application software
curplace EQU $dc ; $dd
bb EQU $de ; bit bucket
countLo EQU $df
countHi EQU $e0
lengths EQU $e1 ; for huffman table creation
; EQU $e2
bTmp EQU $e3 ; temporary pointer for functions
; equ $e4
zp0 EQU $e5
zp1 equ $e6
offset EQU $e7
; EQU $e8
store EQU $d7 ; temporary storage
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; =============================== C16 ====================================
#if MACH == 16
; C16 $1000-$3fff +/4 $1000-$fd00
bitReverse = $2600
CRC = $d8 ; 8,9,a,b
crc32_tab0 = $2700
crc32_tab1 = $2800
crc32_tab2 = $2900
crc32_tab3 = $2a00
PROGEND = $2600
inBuf = $2b00
buf32k = $3000 ; $3000..$8000
bufsz = $5000 ; must be at least $8100 bytes
; (the Shrink method uses the end of the buffer for LZW
; tables, and needs at least one page for output)
S = $2c00 ; $2c00..$2fff
literalTree = S ; Note: has to be in lower half of the memory
;ds.b 256*4
; $00D8-00E8 216-232 Area for use by application software
curplace EQU $dc ; $dd
bb EQU $de ; bit bucket
countLo EQU $df
countHi EQU $e0
lengths EQU $e1 ; for huffman table creation
; EQU $e2
bTmp EQU $e3 ; temporary pointer for functions
; equ $e4
zp0 EQU $e5
zp1 equ $e6
offset EQU $e7
; EQU $e8
store EQU $d7 ; temporary storage
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; ========================================================================
cli ; in case..!?!?
jsr prns
dc.b 147
#if MACH == 64
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$b0,$ae,$b0,$ae,$ae,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$20,$ab,$ae,$ad,$b3
#endif
#if MACH == 4
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$20,$ae,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7b,$ad,$b3
#endif
#if MACH == 128
dc.b $b0,$ae,$20,$20,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$ae,$b0,$ae,$b0,$ae, 13
dc.b $7d,$ae,$7d,$7d,$ab,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$b0,$bd,$ab,$b3
#endif
#if CUSTOM
dc.b "V1.11CUSTOM 19.11.2002",13
#else
dc.b "V1.11 19.11.2002",13
#endif
#if MACH == 64
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$bd,$ad,$bd,$20,$bd
#endif
#if MACH == 4
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$20,$20,$bd
#endif
#if MACH == 128
dc.b $ad,$bd,$ad,$bd,$bd,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$ad,$bd,$ad,$bd
#endif
dc.b " BY PASI'ALBERT'OJALA", 13
dc.b " HTTP://WWW.CS.TUT.FI/%7EALBERT/", 13, 13, 0
#if MACH != 20 && MACH != 16
ldx #0 ; create the CRC32 table (makecrc.c)
crc$ lda #0
sta CRC+3
sta CRC+2
sta CRC+1
stx CRC+0
ldy #8
1$ lsr CRC+3
ror CRC+2
ror CRC+1
ror CRC+0
bcc 0$
lda #$ed
eor CRC+3
sta CRC+3
lda #$b8
eor CRC+2
sta CRC+2
lda #$83
eor CRC+1
sta CRC+1
lda #$20
eor CRC+0
sta CRC+0
0$ dey
bne 1$
lda CRC+0
sta crc32_tab0,x
lda CRC+1
sta crc32_tab1,x
lda CRC+2
sta crc32_tab2,x
lda CRC+3
sta crc32_tab3,x
inx
bne crc$
#else
jsr vic20init
#endif /* V20 */
#if MACH == 64 || MACH == 128
jsr CheckIDE64
#endif
restart lda #0
#if MACH == 64 || MACH == 128
sta inTrack
;sta inSector
sta d64mode
sta first
#endif
sta gzip
idrive$ jsr prns
dc.b "INPUT", 0
lda #14 ; channel #
jsr askdrive
beq idrive$
sta inDrive
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda inDrive
ldx #14
jsr CheckBurst
sta inBurst
#endif
#endif
rfile$ jsr prns
dc.b "INPUT FILE?", 13, 34, 0
lda #0
sta inFile
lda #<inFile
ldx #>inFile
ldy #28 ; max filename length
jsr getstr
lda #0
sta inFile,y
sty inLen
lda #34
jsr OK_KEY
#if MACH != 20 && MACH != 16
jsr ReadDir
lda inLen
beq rfile$
;lda inTrack ; allow non-existing files
;beq rfile$
#endif /* V20 */
odrive$ jsr prns
dc.b "OUTPUT", 0
lda #15
jsr askdrive
beq odrive$
sta outDrive
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda outDrive
ldx #15
jsr CheckBurst
sta outBurst
#endif
#endif
#if CUSTOM == 1
lda outDrive
cmp inDrive
bne oneortwo$
lda fdos
cmp #"A"
bne oneortwo$ ; not a 1541-format disk
lda inTrack
beq oneortwo$ ; we did not find the file from the directory
jsr prns
dc.b "DISSOLVE D64 TO 1541/71 DRIVE ",18,"Y",146,"/",18,"N",146," ? ", 0
onedrive$
jsr getkey
cmp #"N"
beq oneortwo0$
cmp #"Y"
bne onedrive$
jsr OK_KEY
; okay, one drive and D64, set d64mode = $84
lda #$84
sta d64mode ; one-drive mode: custom read and write
jsr initwriter
jmp 2$
oneortwo0$
jsr OK_KEY
; Open input file
oneortwo$
lda #0
sta inMode
#endif
#if CUSTOM == 0
#if MACH == 64 || MACH == 128
lda inBurst
beq openin$ ; can't use burst read -> use sequential read
lda inTrack
bne 2$ ; start t&s known, use burst read
#endif
#endif
openin$ ldx #<inFile
ldy #>inFile
lda inLen
jsr SETNAM
lda #2
ldx inDrive
ldy #0 ; open 2,8,0,"fileName"
jsr SETLFS
jsr OPEN
#if MACH == 64 || MACH == 128
inc inMode
#endif /* V20 */
ldx #14
jsr geterror
cmp #0
beq 2$
jsr CLALL
jsr CLRCHN
ldx #<errorSt
jsr GetBits ; reverse default bit order
jsr CopyLz
jmp Fixed
GetLen tay ; j
;dey ; 1..23 -> 0..22
sty store
ldx cplext-1,y
jsr READBITS ; 0..5 bits
;clc
adc #3 ; does not overflow
ldy store
adc cplens_3-1,y ; 0..255 may overflow
sta countLo
lda #0
rol ;adc #0
sta countHi
rts
; cpdist-index in A
; offset in "offset"
; length in countLo & countHi
CopyLz sta store
tay
ldx cpdext,y
cpx #9
bcs 913$
jsr READBITS ; 1..8 bits
sta offset+0
lda #0
jmp ov$
913$ stx x$+1
ldx #8 ; 9..13 bits
jsr READBITS
sta offset+0
x$ lda #9
and #7
tax
jsr READBITS
ov$ sta offset+1
ldy store
lda cpdistLo,y
;clc ; READBITS cleared it (either one)
adc offset+0
sta offset+0
lda cpdistHi,y
adc offset+1
sta offset+1
; Entry-point for Implode/Reduce
CopyLz2 lda outCmd+1 ; low-byte of current output position
sec
sbc offset+0
sta offset+0
lda outCmd+2 ; high-byte of current output position
sbc offset+1
bcc buffix$ ; wrapped below 0, must be out of buffer -> fix
cmp #>buf32k
bcs bufok$ ; not below 0 and not below buffer start -> ok
; not below 0 but below buffer start -> fix
buffix$ ;clc ; C is clear in both entries
adc #>bufsz
bufok$ sta offset+1
; change dec;lda;cmp #255;bne -> dec;bne
inc countLo
inc countHi
jmp l3$
l0$
ldy #0
lda (offset),y
jsr PutBuffer
inc offset+0
bne l3$
ldy offset+1
iny
cpy #>(buf32k+bufsz) ; wrap to the start of the (ring)buffer
bne l2$
ldy #>buf32k
l2$ sty offset+1
l3$ dec countLo
bne l0$
dec countHi
bne l0$
rts
Dynamic ldx #5
jsr READBITS
;clc
adc #1
sta literalCodes+0 ; + 257
lda #1
sta literalCodes+1
ldx #5
jsr READBITS
;clc
adc #1
sta distCodes ; + 1
ldx #4
jsr READBITS
;clc
adc #4
sta countLo
lda #0
sta countHi
;lda #0
ldx #19
0$ sta codelens,x
dex
bpl 0$
1$ ldx #3
jsr READBITS
ldy countHi
ldx border,y
sta codelens,x
inc countHi
dec countLo
bne 1$
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<distanceTree
sta Places+0
lda #>distanceTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy #0
lda #19
jsr CreateTree
beq tok1$
; invalid tree
rts
;
tok1$ lda literalCodes+0
clc
adc distCodes
sta countLo
lda literalCodes+1
adc #0
sta countHi
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
5$ lda #<distanceTree ; bitlen decode 117 bytes (UnZip 173 bytes)
ldy #>distanceTree
jsr DecodeValue
cmp #16
beq 16$
bcc 015$
; j>16
cmp #17
beq 17$
ldx #7
jsr READBITS
;clc
adc #11
jmp 8$
17$ ldx #3
jsr READBITS
;clc
adc #3
8$ tax
ldy #0
tya ;lda #0
9$ sta (lengths),y
inc lengths+0
bne l0$
inc lengths+1
l0$ dec countLo
bne l1$
dec countHi
l1$ dex
bne 9$
jmp 6$
16$ ; j==16
ldx #2
jsr READBITS
;clc
adc #3
tax
dec lengths+1
ldy #255
7$ lda (lengths),y ; lengths[i-1]
inc lengths+0
bne l2$
inc lengths+1
l2$ sta (lengths),y ; lengths[i]
dec countLo
bne l3$
dec countHi
l3$ dex
bne 7$
inc lengths+1
jmp 6$
015$ ; j<16
ldy #0
sta (lengths),y
inc lengths+0
bne l4$
inc lengths+1
l4$ dec countLo
bne 6$
dec countHi
6$ lda countHi
bpl 5$
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
lda #<literalTree
sta Places+0
lda #>literalTree
sta Places+1
lda #<codelens
sta lengths+0
lda #>codelens
sta lengths+1
ldy literalCodes+1
lda literalCodes+0
jsr CreateTree
beq tok2$
; invalid tree
rts
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
tok2$ lda #<distanceTree
sta Places+0
lda #>distanceTree
sta Places+1
lda #<codelens
clc
adc literalCodes+0
sta lengths+0
lda #>codelens
adc literalCodes+1
sta lengths+1
ldy #0
lda distCod& 255] ^ (crc >> 8))
eor CRC+0 ; 3
tay ; 2
lda crc32_tab0,y ; 4
eor CRC+1 ; 3
sta CRC+0 ; 3
lda crc32_tab1,y ; 4
eor CRC+2 ; 3
sta CRC+1 ; 3
lda crc32_tab2,y ; 4
eor CRC+3 ; 3
sta CRC+2 ; 3
lda crc32_tab3,y ; 4
sta CRC+3 ; 3 =42 cycles/byte = ~7.5 secs for 170.75kB
inc outCmd+1 ;6
bne 2$ ;2/3
inc outCmd+2
lda outCmd+2
cmp #>(buf32k+bufsz)
bne 2$
; Save buffer data buffer32k .. (outCmd)
jsr FlushBuffer
jsr InitBuffer32k
2$
puty ldy #0 ; restore Y value
rts
InitBuffer32k:
; Init buffer pointer
lda #<buf32k
sta outCmd+1
lda #>buf32k
sta outCmd+2
rts
#if MACH != 20 && MACH != 16
; Implode expects a cleared buffer
ClearBuffer:
lda #<buf32k
sta 0$+1
lda #>buf32k
sta 0$+2
lda #0
tay
0$ sta $aa00,y
iny
bne 0$
inc 0$+2
ldx 0$+2
cpx #>(buf32k+bufsz)
bne 0$
rts
#endif /* V20 */
FlushBuffer: ; Can trash A & Y, X
lda mode
cmp #"N" ; skip it
bne do$
rts
do$
#if MACH != 20 && MACH != 16
#if CUSTOM
lda d64mode
bpl donow$
jsr prns
dc.b "INSERT DESTINATION DISK & PRESS ",18,"D",146," ", 0
wait$ jsr getkey
cmp #"D"
bne wait$
jsr OK_KEY
donow$
#endif
jsr onoff
lda d64mode
beq no$
jsr writebuf
jsr CLRCHN
jsr onoff
#if CUSTOM
lda d64mode
bmi ask$
rts
ask$ jsr prns
dc.b "INSERT SOURCE DISK & PRESS ",18,"S",146," ", 0
wait2$ jsr getkey
cmp #"S"
bne wait2$
jmp OK_KEY
#else
rts
#endif
#endif /* V20 */
no$ ldx #3
jsr CHKOUT ; (sends LISTEN+SECOND)
lda #<buf32k
sta bTmp+0
lda #>buf32k
sta bTmp+1
1$
#if MACH == 64 || MACH == 128
lda IDE64present
bpl noIDE64here$ ; IDE64 not found
lda outCmd+1
sec
sbc bTmp+0
tax
lda outCmd+2
sbc bTmp+1
tay
lda #bTmp
inc $d020
jsr IDE64BlockWrite
bcc IDE64writeback$ ;Tried to write to a floppy...
noIDE64here$
#endif
lda bTmp+0
cmp outCmd+1
bne 0$
lda bTmp+1
cmp outCmd+2
bne 0$
IDE64writeback$
jsr CLRCHN
jmp onoff
0$
#if MACH == 20
lda bTmp+1
pha
bpl base$ ; ok, less than $8000
; move $8000..9fff -> $a000..bfff
ora #$20
sta bTmp+1
base$
#endif /* V20 */
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
ldy #0
lda (bTmp),y
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
sta $ff19
jsr CHROUT
#endif
#if MACH == 64 || MACH == 128
sta $d020
jsr CHROUT
#endif
#if MACH == 20
pha
jsr CHROUT
pla
and #7
eor $900f
sta $900f
pla
sta bTmp+1 ; restore "real" address
#endif /* V20 */
inc bTmp+0
bne 1$
inc bTmp+1
jmp 1$
;--------------- Huffman routines ---------------------
;================================================================
;
; struct HufNode
; 0 0-bit value LSB
; 1 0-bit value MSb (D0) + leaf flag (D7)
; 2 1-bit value LSB or jump LO
; 3 1-bit value MSb (D0) + leaf flag (D7) or jump HI (D7=0)
;UnZip: create huffman codes 299 bytes (gunzip 397(new 202) bytes)
IsPat ; Check if there is another code of the current length
; while (1) {
; if (fpos[len] >= fmax)
; return -1;
; if (flens[fpos[len]] == len)
; return fpos[len]++;
; fpos[len]++;
; }
lda len
asl
tax
loop$ ldy fpos+0,x
lda fpos+1,x ; fpos[len]
cmp numval+1
bcc 0$
cpy numval+0
beq not$
0$ cmp #0 ; HI
bne 1$
lda (lengths),y
jmp 2$
1$ inc lengths+1 ; next page
lda (lengths),y
dec lengths+1
2$ cmp len
bne inc$
; got it
lda fpos+1,x
lsr ; shift HI to C
tya ; LO to A
inc fpos+0,x
bne 3$
inc fpos+1,x
3$ ldx #0 ; return zero set (and negative clear)
rts
inc$ inc fpos+0,x
bne loop$
inc fpos+1,x
bpl loop$
not$ ldx #128 ; return zero clear (and negative set)
rts
; Create a decode tree that is in (Places)
; Number of values in A(lo) and Y(hi)
; Length table pointer in (lengths)
CreateTree
sta numval+0
sty numval+1
lda #0
sta len
ldx #2*17-1 ; clear the index counters
0$ sta fpos,x
dex
bpl 0$
; Recursive function
; max recursion depth is equal to the length of the longest codeword (16?)
4
bne locked$
ldx #32
locked$
txa
jsr CHROUT
#endif
lda fblocks+1
jsr puthex
lda fblocks+0
jsr puthex
lda #" "
jsr CHROUT
lda ftype
and #7
asl
asl ; *4
clc
adc #<(ftypstr-4)
tax
lda #>(ftypstr-4)
adc #0
ldy #3
jsr putstr
ldx #32
lda ftype
bmi closed$
ldx #"*"
closed$
txa
jsr CHROUT
lda #34
jsr CHROUT
ldx #<fname
lda #>fname
ldy fnameln
jsr putstr
lda #34
jsr CHROUT
ldy fnameln
tasaa$ lda #" "
jsr CHROUT
iny
cpy #17
bne tasaa$
jsr prns
dc.b 18,"Y",146," ",18,"N",146," ",18,"Q",146," ?", 0
ack$ jsr getkey
bcs ack$
cmp #"Y"
beq this$
cmp #3
beq quit$
cmp #"Q"
beq quit$
cmp #"N"
bne ack$
jsr OK_KEY
jmp dirloop$
quit$ jsr CLRCHN
jsr OK_KEY
lda #0
sta ftrack
jmp gotit$
this$ jsr OK_KEY
ldy #0
cp$ lda fname,y
sta inFile,y
iny
cpy fnameln
bne cp$
sty inLen
jmp gotit$
#endif /* V20 */
askdrive:
sta chan$+1
jsr prns
dc.b " DRIVE? ",18,"8",146,"-",18,"9",146,",1",18,"0",146,"-1",18,"7",146,0
ask$ jsr getkey
bcs ask$
cmp #"0"
bcc ask$ ; smaller than "0"
cmp #":"
bcs ask$ ; ":" or greater
sec
sbc #"0"
cmp #8
bcs ook$
;clc
adc #10 ; 0..7 becomes 10..17, 8..9 stays 8..9
ook$ sta drive$+1
jsr putval
jsr CR
lda #0
jsr SETNAM
chan$ lda #15
drive$ ldx #8
ldy #15 ; open chan,drive,15
jsr SETLFS
jsr OPEN
lda chan$+1
jsr CLOSE
lda ST ; READST
;cmp #0
bne nok$
jsr OPEN ; reopen
lda drive$+1
rts
nok$ lda #0
rts
OK_KEY jsr CHROUT
CR lda #13
jmp CHROUT
#if MACH == 64 || MACH == 128
#if CUSTOM == 0
BREAD sty y$+1
ldx #$c0 ; 1581 BURST: LEXS000N L=logical t&s
lda fdos
cmp #"A"
bne 2$
; 1541/1571/4040-format disks
ldx #$40 ; 1571 BURST: TEBS000N T=no transfer
2$ stx cmdline+2
LDA inTrack
STA cmdline+3
LDA inSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #6
STA cmdlen
ldx #14
JSR sendcmd
SEI
BIT D1ICR
LDA D2PRA
EOR #CLKOUT
STA D2PRA
1$ LDA #8
w1$ BIT D1ICR
BEQ w1$
LDA D1SDR
STA status
and #15
cmp #11 ; disk changed -> no data
beq 5$
LDA D2PRA
EOR #CLKOUT
STA D2PRA
ldy #0
3$ LDA #8
4$ BIT D1ICR
BEQ 4$
LDA D2PRA
EOR #CLKOUT
STA D2PRA
LDA D1SDR
sta inBuf,y
sta $d020
INY
BNE 3$
5$ cli
y$ ldy #0
RTS
BSAVE lda d64mode
cmp #8
bne d6471$
lda #$82
dc.b $2c
d6471$ LDA #$02 ; logical write: $82 for 1581, $02 for 157x
STA cmdline+2
LDA oTrack
STA cmdline+3
LDA oSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #$06
STA cmdlen
ldx #15
JSR sendcmd
LDA #$40
STA oldclk$+1
LDY #0
SEI
1$ SEC
JSR SPIN_OUT
2$ LDA D2PRA
oldclk$ EOR #0
AND #$40
BEQ 2$ ; wait for a change in clock
LDA (bTmp),Y
STA D1SDR ; immediately send the next byte
sta $d020
LDA oldclk$+1
EOR #$40
STA oldclk$+1
LDA #8
4$ BIT D1ICR
BEQ 4$ ; wait until it has been sent
INY
BNE 2$
CLC
JSR SPIN_OUT
BIT D1ICR
LDA D2PRA ; clk lo
ORA #$10
STA D2PRA
LDA #8
w1$ BIT D1ICR
BEQ w1$ ; wait for a fast byte
LDA D1SDR
STA status
LDA D2PRA ; clk hi
AND #$EF
STA D2PRA
CLI
RTS
BERR pha
txa
pha
lda #"E"
jsr CHROUT
lda status
jsr puthex
lda #","
jsr CHROUT
lda status
and #15
tay
lda ePtrLo,y
sta str$+1
lda ePtrHi,y
sta str$+2
ldy #0
str$ lda $aaaa,y
beq end$
jsr CHROUT
iny
bne str$
end$
lda #","
jsr CHROUT
lda #"$"
jsr CHROUT
pla
jsr puthex
lda #","
jsr CHROUT
lda #"$"
jsr CHROUT
pla
jsr puthex
lda #13
jmp CHROUT
e0 dc.b "OK",0
e1 dc.b "SELECTED PARTITION",0
e2 dc.b "NO SECTOR",0
e3 dc.b "NO SYNC",0
e4 dc.b "NO DATA BLOCK",0
e5 dc.b "DATA CRC ERROR",0
e6 dc.b "FORMAT ERROR",0
e7 dc.b "VERIFY ERROR",0
e8 dc.b "WRITE PROTECT",0
e9 dc.b "HEADER CRC ERROR",0
e10 dc.b "DATA EXTENDS INTO NEXT BLOCK",0
e11 dc.b "DISK CHANGED",0
e12 dc.b "DISK FORMAT NOT LOGICAL",0
e13 dc.b "DISK CONTROLLER IC ERROR",0
e14 dc.b "SYNTAX ERROR",0
e15 dc.b "NO DI