puZIP - ZIP File compression#
; DASM V2.12.04 source
; ZIP, 32k window, dynamic Huffman
; 174848 Defl:N 96995 45% 09-13-00 21:08 c4d2f886 t
; PUZIP, 32k window, fixed Huffman
; 174848 Defl:N 107741 39% 00-00-80 00:00 c4d2f886 T
; C64, 8k window, fixed Huffman
; 174848 Defl:N 113643 35% 00-00-80 00:00 c4d2f886 T
; C64, 4k window, fixed Huffman
; 174848 Defl:N 114699 34% 00-00-80 00:00 c4d2f886 T
; C64, 2k window, fixed Huffman
; 174848 Defl:N 119375 32% 00-00-80 00:00 c4d2f886 T
; PKZIP
; =====
; Length Method Size Ratio Date Time CRC-32 Name
; ------ ------ ---- ----- ---- ---- ------ ----
; 174848 Defl:N 60230 66% 12-02-99 18:03 d625f0bd PARTS1.D64
; 174848 Defl:N 24441 86% 12-02-99 18:05 76e851cd PARTS2.D64
; ------ ------ --- -------
; 349696 84671 76% 2 files
; C128
; ====
; Length Method Size Ratio Date Time CRC-32 Name
; ------ ------ ---- ----- ---- ---- ------ ----
; 174848 Defl:N 75580 57% 00-00-80 00:00 d625f0bd PARTS1.D64
; 174848 Defl:N 31867 82% 00-00-80 00:00 76e851cd PARTS2.D64
; ------ ------ --- -------
; 349696 107447 69% 2 files
; ZIP
; ===
; Length Method Size Ratio Date Time CRC-32 Name
; ------ ------ ---- ----- ---- ---- ------ ----
; 174848 Defl:N 59986 66% 02-09-89 00:45 d625f0bd parts1.d64
; 174848 Defl:N 24418 86% 02-09-89 00:45 76e851cd parts2.d64
; ------ ------ --- -------
; 349696 84404 76% 2 files
; C64 39min (1581 files->1581)
; ===
; Length Method Size Ratio Date Time CRC-32 Name
; ------ ------ ---- ----- ---- ---- ------ ----
; 174848 Defl:N 71129 59% 06-07-01 02:39 d625f0bd PARTS1.D64
; 174848 Defl:N 30614 83% 06-07-01 02:39 76e851cd PARTS2.D64
; ------ ------ --- -------
; 349696 101743 71% 2 files
; C64 with lazy matching 47min (1581 files->1581)
; ======================
; Length Method Size Ratio Date Time CRC-32 Name
; ------ ------ ---- ----- ---- ---- ------ ----
; 174848 Defl:N 70548 60% 06-07-01 02:39 d625f0bd PARTS1.D64
; 174848 Defl:N 30491 83% 06-07-01 02:39 76e851cd PARTS2.D64
; ------ ------ --- -------
; 349696 101039 71% 2 files
; Length Size Ratio Date Time CRC-32 Name
; ZIP 174848 96995 45% 02-09-89 00:45 c4d2f886 t
; PuZip - 32k+lazy 174848 106660 39% 09-01-02 02:39 c4d2f886 t
; 0(8k+lazy) 19:50 174848 112701 36% 08-09-02 02:39 c4d2f886 T
; 1(4k+greedy) 15:12 174848 114635 34% 08-09-02 02:39 c4d2f886 T
; 2(2k+greedy) 13:51 174848 118802 32% 08-09-02 02:39 c4d2f886 T
; 3(1k+greedy) 12:57 174848 121699 30% 08-09-02 02:39 c4d2f886 T
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
pos = $0200 ; 4 bytes
arg = $0204 ; 2 bytes
#if MACH == 64 || MACH == 128
IDE64BlockWrite = $DEF1
IDE64BlockRead = $DEF4
IDE64BR = $6e ;$6e $6f
be = $69 ;dc.b 0
D2PRA = $DD00 ; c64 SERIAL PORT LOCATION
D1ICR = $DC0D ; 6526 cia INTERRUPT CONTROL REGISTER
D1SDR = $DC0C ; 6526 cia SERIAL DATA REGISTER
#endif
; name -- input file name 16+2
CA_CRC = 18 ; crc32 -- cyclic redundancy check
CA_CSize = 22 ; csize -- compressed size
CA_USize = 26 ; usize -- uncompressed size
CA_LHdr = 30 ; lhdroff -- local header offset
CA_FLen = 34 ; filename length
CA_TS = 35 ; starting track & sector, if any
CA_Mode = 37 ; compress mode -- "S" or "Y"
CASIZE = 38
; =============================== VIC20 ====================================
#if MACH == 20
; 16k expansion required - $1200-$5fff
MAX_MATCH = 255 ;$0ff
BLOCK_SIZE = 4*256 ;$400 ; must be rounded to 256 bytes and power of 2
; Maximum for BLOCK_SIZE is 32768
LSHIFT = 4 ; 4 and 5 supported, (3 too slow, 6 memory-hungry)
LSIZE = (1<<LSHIFT)
lPairSize = 4*LSIZE*LSIZE
bSkipSize = 2*BLOCK_SIZE
bufferSize = BLOCK_SIZE + MAX_MATCH+1
; lPair must be before bSkip in memory, both must be aligned to page
lPair = $4c00 ; $4c00..$4fff unsigned long lPair[16*16]
bSkip = lPair+lPairSize
; $5000..$57ff unsigned short bSkip[BLOCK_SIZE]
buffer = $5800 ; $5800..$5cff unsigned char buffer[BLOCK_SIZE + MAX_MATCH]
;outbuf = $2b00
outend = $4a00 ; $2b00..$4a00 ; 181 files leaves 1k output buffer
MAXFILES = 181
byte = $2
CRC = $6a ; $6a..6d
bTmp = $14 ; $14,$15
rPtr = $f7 ; $f7,$f8
wPtr = $f9 ; $f9,$fa
zp0 = $fb
zp1 = $fc
tmp = $fd
CAPtr = $fe ; $fe,$ff
crc32_tab0 = $5d00
crc32_tab1 = $5e00
crc32_tab2 = $5f00
crc32_tab3 = $4b00
inBuf = $4a00
ORG $1201
DC.B $0b,$12,20,0 ; '20 SYS4621'
DC.B $9e,$34,$36,$32
DC.B $31,0,0,0
#endif
; =============================== C16 ====================================
#if MACH == 16
; C16 $1000-$3fff +/4 $1000-$fd00
MAX_MATCH = 255 ;$0ff
BLOCK_SIZE = 4*256 ;$400 ; must be rounded to 256 bytes and power of 2
; Maximum for BLOCK_SIZE is 32768
LSHIFT = 4 ; 4 and 5 supported, (3 too slow, 6 memory-hungry)
LSIZE = (1<<LSHIFT)
lPairSize = 4*LSIZE*LSIZE ; $400
bSkipSize = 2*BLOCK_SIZE ; $800
bufferSize = BLOCK_SIZE + MAX_MATCH+1 ; $500
; lPair must be before bSkip in memory, both must be aligned to page
lPair = $2a00 ; $2a00..$2dff unsigned long lPair[16*16]
bSkip = lPair+lPairSize
; $2e00..$35ff unsigned short bSkip[BLOCK_SIZE]
buffer = $3600 ; $3600..$3aff unsigned char buffer[BLOCK_SIZE + MAX_MATCH]
outend = lPair
MAXFILES = 26 ; 26 leaves $100 for output buffer
; $00D8-00E8 216-232 Area for use by application software
byte = $dd
CRC = $e0 ; $e0..$e3
bTmp = $de ; $de,$df
rPtr = $e4 ; $e4,$e5
wPtr = $e6 ; $e6,$e7
zp0 = $db
zp1 = $dc
tmp = $da
CAPtr = $d8 ; $d8,$d9
crc32_tab0 = $3b00
crc32_tab1 = $3c00
crc32_tab2 = $3d00
crc32_tab3 = $3e00
inBuf = $3f00
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
; =============================== Plus/4 ====================================
#if MACH == 4
; C16 $1000-$3fff +/4 $1000-$fd00
MAX_MATCH = 255 ;$0ff
BLOCK_SIZE = 32*256 ;$2000 ; must be rounded to 256 bytes and power of 2
; Maximum for BLOCK_SIZE is 32768
LSHIFT = 5 ; 4 and 5 supported, (3 too slow, 6 memory-hungry)
LSIZE = (1<<LSHIFT)
lPairSize = 4*LSIZE*LSIZE ; $1000
bSkipSize = 2*BLOCK_SIZE ; $4000
bufferSize = BLOCK_SIZE + MAX_MATCH+1 ; $2100
; lPair must be before bSkip in memory, both must be aligned to page
lPair = $8000 ; $8000..$8fff unsigned long lPair[32*32]
bSkip = lPair+lPairSize
; $9000..$cfff unsigned short bSkip[BLOCK_SIZE]
buffer = $d400 ; $d400..$f4ff unsigned char buffer[BLOCK_SIZE + MAX_MATCH]
outend = $6000
MAXFILES = 254 ; 254 leaves $344c for output buffer
crc32_tab0 = $d300
crc32_tab1 = $d200
crc32_tab2 = $d100
crc32_tab3 = $d000
inBuf = $7f00
; $00D8-00E8 216-232 Area for use by application software
byte = $dd
CRC = $e0 ; $e0..$e3
bTmp = $de ; $de,$df
rPtr = $e4 ; $e4,$e5
wPtr = $e6 ; $e6,$e7
zp0 = $db
zp1 = $dc
tmp = $da
CAPtr = $d8 ; $d8,$d9
ORG $1001
DC.B $0b,$10,20,0 ; '20 SYS4109'
DC.B $9e,$34,$31,$30
DC.B $39,0,0,0
#endif
#if MACH == 64
; =============================== C64 =====================================
; $14..15, 2, $9e..9f
; $f7..ff
MAX_MATCH = 255 ;$0ff
BLOCK_SIZE = 32*256 ;$2000 ; must be rounded to 256 bytes and power of 2
LSHIFT = 5 ; 4 and 5 supported, (3 too slow, 6 memory-hungry)
LSIZE = (1<<LSHIFT)
lPairSize = 4*LSIZE*LSIZE ; $1000
bSkipSize = 2*BLOCK_SIZE ; $4000
bufferSize = BLOCK_SIZE + MAX_MATCH+1 ; $2100
; lPair must be before bSkip in memory, both must be aligned to page
lPair = $7800 ; $7800..$87ff unsigned long lPair[32*32]
bSkip = lPair+lPairSize
; $8800..$c7ff unsigned short bSkip[BLOCK_SIZE]
buffer = $d000 ; $d000..$f0ff unsigned char buffer[BLOCK_SIZE + MAX_MATCH]
outend = $7800
MAXFILES = 254 ; 255 means disk image
crc32_tab0 = $c900
crc32_tab1 = $ca00
crc32_tab2 = $cb00
crc32_tab3 = $cc00
inBuf = $cd00
; CE00 and CF00 reserved for REU/RamDOS
byte = $2
CRC = $6a ; $6a..6d
bTmp = $14 ; $14,$15
rPtr = $f7 ; $f7,$f8
wPtr = $f9 ; $f9,$fa
zp0 = $fb
zp1 = $fc
tmp = $fd
CAPtr = $fe ; $fe,$ff
FASTSER = $02a3
ORG $0801
DC.B $0b,8,64,0 ; '64 SYS2061'
DC.B $9e,$32,$30,$36
DC.B $31,0,0,0
lda #$36
sta 1
#endif
; =============================== C128 =====================================
#if MACH == 128
MAX_MATCH = 255 ;$0ff
BLOCK_SIZE = 32*256 ;$2000 ; must be rounded to 256 bytes and power of 2
LSHIFT = 5 ; 4 and 5 supported, (3 too slow, 6 memory-hungry)
LSIZE = (1<<LSHIFT)
lPairSize = 4*LSIZE*LSIZE ;$1000
bSkipSize = 2*BLOCK_SIZE ;$4000
bufferSize = BLOCK_SIZE + MAX_MATCH+1 ; $2100
buffer = $9f00 ; $9f00..$bfff unsigned char buffer[BLOCK_SIZE + MAX_MATCH]
; lPair must be before bSkip in memory, both must be aligned to page
; lPair and bSkip are now in bank1
lPair = $1000 ; $1000..$1fff unsigned long lPair[32*32]
bSkip = lPair+lPairSize
; $2000..$5fff unsigned short bSkip[BLOCK_SIZE]
outend = $9f00 ; $3d00..$9eff ; 254 files leaves 15k outpuf buffer
MAXFILES = 254 ; 255 means disk image
byte = $86
tmp = $87
CRC = $6a ; $6a..6d
bTmp = $88 ; $88,$89
rPtr = $8a ; $8a,$8b
wPtr = $fa ; $fa,$fb
zp0 = $fc
zp1 = $fd
CAPtr = $fe ; $fe,$ff
prns = $ff7d
crc32_tab0 = $1300
crc32_tab1 = $1400
crc32_tab2 = $1500
crc32_tab3 = $1600
inBuf = $1700
FASTSER = $0a1c
SETBANK = $ff68 ; sta c6 stx c7
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
JSRFAR = $02CD ; JSR XXXX to Any Bank & Return
; 02de return memory config
;0002 Bank Number, Jump to SYS Address
;0003-0004 SYS address, MLM register PC
;0005-0009 SYS and MLM register save (SR, A, X, Y, SP)
ORG $1c01
DC.B $0b,$1c,128,0 ; '128 SYS7181'
DC.B $9e,$37,$31,$38
DC.B $31,0,0,0
lda $02de
pha
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
jsr bank1install
#endif
cli ; just in case..!?!?
jsr prns
dc.b 147
#if MACH == 4
dc.b $b0,$ae,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$20,$ae,$ae, 13
dc.b $ab,$bd,$ae,$ae,$ac,$be,$7d,$ab,$bd,$20,$7b,$ad,$b3
#endif
#if MACH == 16
dc.b $b0,$ae,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$b0,$ae,$ae,$b0,$ae, 13
dc.b $ab,$bd,$ae,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$20,$7d,$ab,$ae
#endif
#if MACH == 64
dc.b $b0,$ae,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$b0,$ae,$b0,$ae,$ae,$ae, 13
dc.b $ab,$bd,$ae,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$20,$ab,$ae,$ad,$b3
#endif
#if MACH == 128
dc.b $b0,$ae,$20,$20,$b0,$ae,$20,$b0,$ae,$20,$ae,$b0,$ae,$b0,$ae, 13
dc.b $ab,$bd,$ae,$ae,$ac,$be,$7d,$ab,$bd,$20,$7d,$b0,$bd,$ab,$b3
#endif
dc.b " V1.12 19.11.2002",13
#if MACH == 4
dc.b $bd,$20,$ad,$bd,$ad,$bd,$bd,$bd,$20,$be,$20,$20,$bd
#endif
#if MACH == 16
dc.b $bd,$20,$ad,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$bd,$b1,$ad,$bd
#endif
#if MACH == 64
dc.b $bd,$20,$ad,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$bd,$ad,$bd,$20,$bd
#endif
#if MACH == 128
dc.b $bd,$20,$ad,$bd,$ad,$bd,$bd,$bd,$20,$be,$ad,$ad,$bd,$ad,$bd
#endif
dc.b " BY PASI'ALBERT'OJALA", 13
#if MACH != 20
dc.b " HTTP://WWW.CS.TUT.FI/%7EALBERT/", 13, 13, 0
#else
dc.b " HTTP://WWW.CS.TUT.FI/%7EALBERT/", 13, 13, 0
#endif
lda #8
sta bits
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
#if MACH == 64
sei
ldy #$34
sty 1
#endif
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$
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 64
ldy #$36
sty 1
cli
#endif
restart
#if MACH == 64 || MACH == 128
jsr on ; screen on / 2MHz mode if possible
#endif
idrive$ jsr prns
dc.b "INPUT", 0
lda #14 ; channel #
jsr askdrive
beq idrive$
sta inDrive
#if MACH == 64 || MACH == 128
jsr CheckBurst
jsr CheckIDE64
#endif
lda #0
sta files
lda #<CA
sta CAPtr+0
lda #>CA
sta CAPtr+1
jsr ReadDir
; Make the output buffer as big as possible,
; i.e. it starts right after the last file entry.
lda CAPtr+1 ; HI
sta obufhi ; start of output buffer
inc obufhi ; right after filenames
lda files
cmp #255
beq odrive$
cmp #0
bne files$
iagain$ lda #14 ; no files -> try again
jsr CLOSE
jmp idrive$
files$ ldx #<files
ldy #>files
lda #1
jsr putdec
jsr prns
dc.b " FILES",13, 0
odrive$ jsr prns
dc.b "OUTPUT", 0
lda #15
jsr askdrive
bcs iagain$ ; RUN/STOP pressed - back to input drive
beq odrive$ ; device not present - ask again
sta zipDrive
lda files
cmp #255
bne ofile$
cmp inDrive
bne ofile$
; image compression and one drives
lda #15
jsr CLOSE
jsr prns
dc.b "DISK IMAGE COMPRESSION NEEDS TWO DRIVES",13,0
jmp odrive$
ofile$ jsr prns
dc.b "ZIP FILE?", 13, 34, 0
lda #0
sta zipFile
lda #<zipFile
ldx #>zipFile
ldy #28 ; max filename length
jsr getstr
sty zipLen
lda #34
jsr OK_KEY
lda zipLen
bne onok$
lda #15 ; an empty filename.. ask the drive again
jsr CLOSE
jmp odrive$
onok$ lda zipFile+0
cmp #"@"
bne oopen$
; a disk command..
lda zipLen
cmp #1
beq orerr$
ldx #15
jsr CHKOUT
ldy #1
ocmd$ lda zipFile,y
jsr CHROUT
iny
cpy zipLen
bne ocmd$
jsr CLRCHN
orerr$ ldx #15
jsr geterror
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
jmp ofile$
oopen$ ldx #<zipFile
ldy #>zipFile
lda zipLen
jsr SETNAM
lda #3
ldx zipDrive
ldy #1 ; open 3,8,1,"fileName"
jsr SETLFS
jsr OPEN
ldx #15
jsr geterror
cmp #0
beq 2$
lda #3
jsr CLOSE
jsr CLRCHN
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
jmp ofile$
2$ jsr CLRCHN
lda files
sta filecnt
lda #<CA
sta CAPtr+0
lda #>CA
sta CAPtr+1
lda #0
sta outSize+0
sta outSize+1
sta outSize+2
sta outSize+3
jsr InitBuffer32k
jsr prns
dc.b "ZIP COMMENT?", 13, 34, 0
lda #0
sta zipComment
lda #<zipComment
ldx #>zipComment
ldy #36
jsr getstr
sty zipCommentLen
lda #34
jsr OK_KEY
; ---------------------------------------------
fileloop:
#if MACH == 64 || MACH == 128
lda #0
sta inMode
#endif
lda files
cmp #255
beq disk$
jmp fi$
; D64/D71/D81 read -- open direct access buffer if needed
disk$ ldy #CA_Mode
lda #"Y" ; always compress disk images
sta (CAPtr),y
ldy #0
dn$ lda diskName,y
bpl nlow$
eor #$a0
nlow$ sta (CAPtr),y
beq nend$ ; NUL -> end of file name
iny
cpy #16
bne dn$
nend$
; append .d81 .d71 or .d64
cpy #15
bcc append$ ; if 0..14 chars, just append
ldy #14 ; if 15.. overwrite the end
append$ lda #"."
sta (CAPtr),y
iny
lda #"D"
sta (CAPtr),y
iny
lda #"8"
sta (CAPtr),y
iny
lda #"1"
sta (CAPtr),y
lda fdos
cmp #"D"
beq dok$ ; ".D81"
dey
lda #"7"
sta (CAPtr),y
iny
bit fflag
bmi dok$ ; ".D71"
dey
lda #"6"
sta (CAPtr),y
iny
lda #"4"
sta (CAPtr),y ; ".D64"
dok$
iny
tya
ldy #CA_FLen
sta (CAPtr),y
ldy #1
sty inTrack
dey ; ldy #0
sty inSector
#if MACH == 64 || MACH == 128
lda inBurst
beq direct$ ; can't use burst read -> use sequential read
inc inMode ; burst mode, direct-access file not opened
jmp 3$
direct$
#endif
ldx #<d64chan$
ldy #>d64chan$
lda #1
jsr SETNAM
lda #2
ldx inDrive
tay ;ldy #2 ; open 2,8,2,"#"
jsr SETLFS
jsr OPEN
ldx #14
jsr geterror
cmp #0
beq noerr1$
jsr CLRCHN
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
noerr1$ lda #"2"
jsr initbp
jmp 3$
d64chan$
dc.b "#"
fi$
#if MACH == 64 || MACH == 128
lda inBurst
beq open$ ; can't use burst read -> use sequential read
ldy #CA_TS
lda (CAPtr),y
beq open$ ; no T&S -> use sequential read
sta inTrack
iny
lda (CAPtr),y
sta inSector
inc inMode
jmp 3$
#endif
open$ ldy #CA_FLen
lda (CAPtr),y
ldx CAPtr+0
ldy CAPtr+1
jsr SETNAM
lda #2
ldx inDrive
ldy #0 ; open 2,8,0,"fileName"
jsr SETLFS
jsr OPEN
ldx #15
jsr geterror
cmp #0
beq 3$
lda #2
jsr CLOSE
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
jsr CR
jmp fileloop ; TODO: update fields etc.
; File opened and/or inTrack/inSector initialized
3$ lda #0
sta be
sta ST
ldx #3
ldy #CA_LHdr+3
5$ lda outSize+0,x
sta (CAPtr),y ; CA[files].lhdroff = curbyte;
dey
dex
bpl 5$
ldy #0
lhdr$ lda lhdr,y ; Put local file header
jsr PutBuffer
iny
cpy #26
bne lhdr$
ldy #CA_FLen
lda (CAPtr),y
sta curlen ; put current file name length
jsr PutBuffer
lda #0
jsr PutBuffer
lda #0
jsr PutBuffer
lda #0
jsr PutBuffer
jsr InitBits
ldy #0
floop$ lda (CAPtr),y ; put filename
bpl low$
eor #$a0
low$ jsr PutBuffer
lda (CAPtr),y
jsr CHROUT
iny
cpy curlen
bne floop$
lda #" "
jsr CHROUT
ldx #3
6$ lda #255
sta CRC+0,x
lda #0
sta usize+0,x
lda outSize+0,x
sta cstart+0,x
dex
bpl 6$
lda #0
sta zipMode ; not stored
file ldy #CA_Mode
lda (CAPtr),y
cmp #"S"
beq stored$
jsr Huffman ; pass speed parameter in A
jmp tail$
stored$ jsr Stored
tail$ ; Put data descriptor header
lda #$50
jsr PutBuffer
lda #$4b
jsr PutBuffer
lda #$07
jsr PutBuffer
lda #$08
jsr PutBuffer
ldx #3
ldy #CA_CRC+3
crc$ lda CRC+0,x
eor #255
sta (CAPtr),y
dey
dex
bpl crc$
ldx #3
ldy #CA_CSize
sec ; csize = curbyte - cstart;
subl$ lda outSize-CA_CSize,y
sbc cstart-CA_CSize,y
sta csize-CA_CSize,y
sta (CAPtr),y
iny
dex
bpl subl$
ldx #3
ldy #CA_USize
ul$ lda usize-CA_USize,y
sta (CAPtr),y
iny
dex
bpl ul$
; put CRC, CSize and USize
ldx #12
ldy #CA_CRC
cs$ lda (CAPtr),y
jsr PutBuffer
iny
dex
bne cs$
#if MACH == 64 || MACH == 128
jsr on
lda inMode
bne noclose$ ; used burst read -> no close
#endif
ldx #14
jsr geterror
cmp #0
beq noerr$
jsr CLRCHN
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
noerr$
lda #2
jsr CLOSE
noclose$
jsr CLRCHN
ldx #<usize
ldy #>usize
lda #4
jsr putdec
lda #"="
jsr CHROUT
lda #">"
jsr CHROUT
ldx #<csize
ldy #>csize
lda #4
jsr putdec
lda #" "
jsr CHROUT
jsr putratio
lda #"%"
jsr CHROUT
jsr CR
lda files
cmp #255
beq 4$
lda CAPtr+0
clc
adc #CASIZE
sta CAPtr+0
bcc noc$
inc CAPtr+1
noc$ dec filecnt
beq 4$
jmp fileloop
; ---------------------------------------------
4$ ldx #3
5$ lda #0
sta csize,x
lda outSize+0,x
sta cstart+0,x
dex
bpl 5$
lda files
sta filecnt
lda #<CA
sta CAPtr+0
lda #>CA
sta CAPtr+1
headerloop
ldy #0
ghdr$ lda ghdr,y ; Put global header
jsr PutBuffer
iny
cpy #16
bne ghdr$
ldy #CA_CRC
1$ lda (CAPtr),y
jsr PutBuffer
iny
cpy #CA_LHdr
bne 1$
ldy #CA_FLen
lda (CAPtr),y
sta curlen
jsr PutBuffer
ldy #10 ;12
3$ lda #0
jsr PutBuffer
dey
bpl 3$
lda #$b4
jsr PutBuffer
lda #$80
jsr PutBuffer
ldy #CA_LHdr
lda (CAPtr),y
jsr PutBuffer
iny
lda (CAPtr),y
jsr PutBuffer
iny
lda (CAPtr),y
jsr PutBuffer
iny
lda (CAPtr),y
jsr PutBuffer
ldy #0
4$ lda (CAPtr),y ; put filename
bpl low$
eor #$a0
low$ jsr PutBuffer
iny
cpy curlen
bne 4$
lda curlen
clc
adc #46
bcc 7$
inc csize+1
clc
7$ adc csize+0
sta csize+0
bcc 6$
inc csize+1
bne 6$
inc csize+2
bne 6$
inc csize+3
6$
lda files
cmp #255
beq 0$
lda CAPtr+0
clc
adc #CASIZE
sta CAPtr+0
bcc noc$
inc CAPtr+1
noc$ dec filecnt
beq 0$
jmp headerloop
0$ ldy #0
ehdr$ lda ehdr,y ; put end of header
jsr PutBuffer
iny
cpy #8
bne ehdr$
lda files
cmp #255
bne 21$
lda #1
21$ jsr PutBuffer
lda #0
jsr PutBuffer
lda files
cmp #255
bne 22$
lda #1
22$ jsr PutBuffer
lda #0
jsr PutBuffer
ldy #0
11$ lda csize+0,y
jsr PutBuffer
iny
cpy #4
bne 11$
ldy #0
2$ lda cstart+0,y
jsr PutBuffer
iny
cpy #4
bne 2$
lda zipCommentLen ; Zip comment length
jsr PutBuffer
lda #0
jsr PutBuffer
lda zipCommentLen
beq flush$
ldy #0
33$ lda zipComment,y
bpl 34$
eor #$a0
34$ jsr PutBuffer
iny
cpy zipCommentLen
bne 33$
flush$ jsr FlushBuffer
#if MACH == 64 || MACH == 128
jsr on
#endif
lda #3
jsr CLOSE
;lda #14
;jsr CLOSE
;lda #15
;jsr CLOSE
jsr CLALL
jsr CLRCHN
#if MACH == 64
lda #$37
sta 1
#endif
#if MACH == 128
pla
sta $ff00 ; restore memory config
pla
sta $02de ; restore return memory config
#endif
cli ; just in case
rts
Huffman:
ldy #0
cmp #"Y"
beq speed$
cmp #"0"
beq speed$
iny
cmp #"1"
beq speed$
iny
cmp #"2"
beq speed$
iny
speed$ sty speed ; speed = 0..3
;==============================================================
; lPair must be before bSkip in memory
; memset(lPair, 0, sizeof(lPair));
; memset(bSkip, 0, sizeof(bSkip));
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
#if MACH == 64
sei
ldy #$34
sty 1
#endif
#if MACH == 128
jsr ClearSearch
#else
lda #>lPair
sta clr$+2
ldx #>(lPairSize+bSkipSize)
ldy #0
tya ;lda #0
clr$ sta $aa00,y
iny
bne clr$
inc clr$+2
dex
bne clr$
#endif
;lda #0
sta oMaxlen ; oMaxlen = 0; /* 0 = not started */
sta oChar ; oChar = 0;
sta eof ; eof = 0;
sta skip ; skip = 0;
sta pos+0 ; p = 0;
sta pos+1
sta pos+2
sta pos+3
sta buc ; bu = 0; bytes in the lookahead 'buffer'
lda #<buffer ; wPtr = rPtr = &buffer[0];
sta wPtr+0
sta rPtr+0
lda #>buffer
sta wPtr+1
sta rPtr+1
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 64
ldy #$36
sty 1
cli
#endif
lda #1 ; last block, yes
ldx #1
jsr PutBits
lda #1 ; fixed huffman
ldx #2
jsr PutBits
dataloop$
; Fill the lookahead buffer if no EOF seen yet..
lda eof
bne nofill$
; bu is 0 for first entry, bu is decremented each dataloop$,
; thus bu is never MAX_MATCH when while is entered
;ldx #2
;jsr CHKIN ;while (!eof && bu < MAX_MATCH) {
fill$ ;jsr CHRIN ; int c = fgetc(fp);
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 64
ldy #$36
sty 1
cli
#endif
jsr GetByte ; if (c == EOF) {
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
#if MACH == 64
sei
ldy #$34
sty 1
#endif
ldy #0 ; eof = 1;
sta (wPtr),y ; break;
sta delta$+1 ; } else {
jsr updcrc ; crc32 = updcrc(c, crc32);
lda wPtr+1
cmp #>buffer ; *wPtr = c;
bne nodelta$ ; if (wPtr < &buffer[MAX_MATCH]) {
tax
clc
adc #>BLOCK_SIZE
sta wPtr+1
delta$ lda #0
sta (wPtr),y ; *(wPtr + BLOCK_SIZE) = c;
stx wPtr+1
nodelta$ ; }
inc wPtr+0 ; wPtr++;
bne wpe$
inc wPtr+1 ; if (wPtr == &buffer[BLOCK_SIZE]) {
lda wPtr+1 ; wPtr = &buffer[0];
cmp #>(buffer+BLOCK_SIZE)
bne wpe$
lda #>buffer
sta wPtr+1 ; }
wpe$ inc buc ; bu++;
bit ST
bvc noeof$
lda #0
sta ST
inc eof
bne nofill$
noeof$ ; }
lda buc ; bytes in the lookahead 'buffer'
cmp #MAX_MATCH
bne fill$ ;}
;jsr CLRCHN
nofill$
; Create index to our search structure and the
; corresponding pointer from the search string's
; two first characters.
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
#if MACH == 64
sei
ldy #$34
sty 1
#endif
ldy #1
lda (rPtr),y
tax
dey
lda (rPtr),y
#if MACH == 128
sta arg+0
stx arg+1
jsr UpdSearch
#else
; no check.. it doesn't matter if we read 1 byte off the end
updsearch$ ;if (bu > 1) {
; long off;
; unsigned short index =
asl ; ((*rPtr & (LSIZE-1)) << LSHIFT) |
asl ; (*(rPtr+1) & (LSIZE-1));
asl ; long *lPairPtr = &lPair[index];
#if LSHIFT == 4
asl ; shifting only leaves 4 bits
sta zp0
txa ; HI
and #15 ; take only 4 bits
lsr ; shift 2 bits to LO part, because
ror zp0 ; array element is 4 bytes
lsr
ror zp0 ; leaves 2 bits in HI part
#endif
#if LSHIFT == 5
sta zp0 ; shifting only leaves 5 bits
txa
and #31 ; take only 5 bits
lsr ; shift 1 bit to LO part
ror zp0 ; leaves 3 bits in HI part
#endif
;clc ; C already clear, because zp0 is *8 (or *16)
adc #>lPair
sta zp1
lda pos+0 ; unsigned short *tmp = &bSkip[p & (BLOCK_SIZE-1)];
sta bTmp+0
lda pos+1
and #>(BLOCK_SIZE-1)
asl bTmp+0
rol
;clc ; C already clear, because BLOCK_SIZE <= 32768
adc #>bSkip
sta bTmp+1
; off = p - *lPairPtr;
; if (off < (BLOCK_SIZE-MAX_MATCH)) {
; *tmp = off;
; } else {
; *tmp = 0;
; }
ldy #0
lda pos+0
sec
sbc (zp0),y
sta off0$+1
iny
lda pos+1
sbc (zp0),y
sta off1$+1
iny
lda pos+2
sbc (zp0),y
sta off2$+1
iny
lda pos+3
sbc (zp0),y
off2$ ora #0
bne ptr0$ ;16 top bits != 0
lda off1$+1
cmp #>(BLOCK_SIZE-MAX_MATCH)
bcc ptr$ ; HI byte < --> ok!
; HI byte >=
;bne ptr0$ ; HI byte > --> not ok
;todo: compare low byte -- but it doesn't matter much..
ptr0$ lda #0 ; too far or not found
sta off0$+1
sta off1$+1
; Update search structure pointers
ptr$ ldy #0
off0$ lda #0
sta (bTmp),y ; *tmp=..
iny
off1$ lda #0
sta (bTmp),y
dey ;ldy #0
lda pos+0
sta (zp0),y ; *lPairPtr = p;
iny
lda pos+1
sta (zp0),y
iny
lda pos+2
sta (zp0),y
iny
lda pos+3
sta (zp0),y
#endif
; Skip or perform search
lda skip ;if (skip) {
beq noskip$
dec skip ; skip--;
jmp eskip$
;} else {
noskip$ lda #1 ;short maxlen = 1, maxpos = 0, j;
sta maxlen
lda #<(BLOCK_SIZE-MAX_MATCH)
sta left+0 ;int left = BLOCK_SIZE - MAX_MATCH;
lda #>(BLOCK_SIZE-MAX_MATCH)
sta left+1
#if 1
ldy speed
beq leftok$
ll$ lsr left+1
ror left+0
dey
bne ll$
leftok$
#endif
lda pos+0 ;unsigned short im = p & (BLOCK_SIZE-1);
sta im+0
lda pos+1
and #>(BLOCK_SIZE-1)
sta im+1
ldy #0
lda (rPtr),y
sta nChar
while$ lda im+0 ;while ((j = bSkip[im])) {
asl ; array element size 2
sta zp0
lda im+1
rol
;clc ; C already clear, because im < 32768
adc #>bSkip
sta zp1
#if MACH == 128
sei
ldy #1
ldx #1 ; RAM1
lda #zp0
jsr READBANK ; lda (ZP),y bank in X, ZP in A
sta j1$+1
dey
ldx #1 ; RAM1
lda #zp0
jsr READBANK
sta j0$+1
cli
#else
ldy #1
lda (zp0),y
sta j1$+1
dey
lda (zp0),y
sta j0$+1
#endif
j1$ ora #0
beq break$
lda left+0
sec
j0$ sbc #0
sta left+0 ;left -= j;
lda left+1
sbc j1$+1 ;if (left < 0) {
sta left+1 ; break;
bmi break$ ;}
;im = (im - j) & (BLOCK_SIZE-1);
lda im+0
sec
sbc j0$+1
sta im+0
sta ap$+1
lda im+1
sbc j1$+1
and #>(BLOCK_SIZE-1)
sta im+1 ;ap = &buffer[im];
clc
adc #>buffer
sta ap$+2
ldy #0 ;j = 0;
ap$ lda $aaaa,y ;while (*ap++ == rPtr[j] && ++j < MAX_MATCH)
cmp (rPtr),y ; ;
bne out$
iny
bne ap$
; All 256 bytes were equal,
; but we currently handle only 8-bit MAX_MATCH i.e. 0..255
ldy #MAX_MATCH
out$ cpy maxlen ;if (j > maxlen) {
bcc while$ ; maxlen = j;
beq while$ ; maxpos = (int)(&rPtr[j] - ap) & (BLOCK_SIZE-1);
new$ sty maxlen ; if (maxlen == MAX_MATCH ||
lda rPtr+0 ; *rPtr == *(rPtr+1)) {
sec ; break;
sbc ap$+1 ; }
sta maxpos+0
lda rPtr+1
sbc ap$+2
and #>(BLOCK_SIZE-1)
sta maxpos+1
cpy #MAX_MATCH
beq break$
lda nChar
ldy #1
cmp (rPtr),y
beq break$ ; if seems like rle, got long enough..
;}
jmp while$
break$
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 64
ldy #$36
sty 1
cli
#endif
; Check if we accidentally compared off the end..
lda buc
cmp maxlen ;if (maxlen > bu) {
bcs 0$
sta maxlen ; maxlen = bu;
0$ ;}
lda maxlen ;if (maxlen >= 3) {
sec
sbc #3
bcs enough$
jmp lit$
enough$
#if 1
lda speed ; if (speed!=0) {
beq lazylz$
jsr PutLzNow ; PutLz(fpout, maxlen, maxpos);
lda maxlen ; skip = maxlen-1;
sec
jmp cont0$ ; oMaxlen = 0;
; } else
#endif
lazylz$ lda oMaxlen
sec ;if (oMaxlen >= maxlen) {
sbc maxlen ;if (oMaxlen - maxlen >= 0) {
bcc eelse$
jsr PutLz ; PutLz(fpout, oMaxlen, oMaxpos);
lda oMaxlen
clc
cont0$ sbc #1
sta skip ; skip = oMaxlen-2;
lda #0
sta oMaxlen ; oMaxlen = 0; /* nothing in fifo */
beq eend$
eelse$ lda oMaxlen ;} else {
beq e2end$ ; if (oMaxlen)
clc
lda oChar
jsr PutFixed ; PutFixed(fpout, oChar);
e2end$ lda maxlen
sta oMaxlen ; oMaxlen = maxlen;
lda maxpos+0
sta oMaxpos+0
lda maxpos+1
sta oMaxpos+1 ; oMaxpos = maxpos;
eend$ jmp lend$ ;}
lit$
#if 1
lda speed ;} else {
beq lazylit$ ;if (speed!=0) {
clc
lda nChar ; PutFixed(fpout, nChar);
jsr PutFixed
jmp cont1$ ; oMaxlen = 0;
;} else
#endif
lazylit$
lda oMaxlen
sec
sbc #3 ;if (oMaxlen >= 3) {
bcc lelse$
jsr PutLz ; PutLz(fpout, oMaxlen, oMaxpos);
lda oMaxlen
sec
sbc #2
sta skip ; skip = oMaxlen-2;
cont1$ lda #0
sta oMaxlen ; oMaxlen = 0; /* nothing in fifo */
beq lend$
lelse$ lda oMaxlen ;} else {
beq lnolit$ ; if (oMaxlen)
clc
lda oChar
jsr PutFixed ; PutFixed(fpout, oChar);
lnolit$ lda #1
sta oMaxlen ; oMaxlen = 1;
lend$ ;}
lda nChar
sta oChar ; oChar = *rPtr;
eskip$ ;}
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 64
ldy #$36
sty 1
cli
#endif
inc pos+0 ;p++;
bne pe$
inc pos+1
bne pe$
inc pos+2
bne pe$
inc pos+3
pe$
#if 1 ; progress indicator
lda pos+0
bne noprgupd$
#if MACH == 64 || MACH == 128
lda pos+1
and #31
cmp #4
bcs 123$
jsr on ; block 0,1,2, 32,33,34, 64,65,66.. turn screen on
jmp 124$
123$ ;sec
jsr off ; block 3, 35, 67, 99.. screen off / 2MHz
124$
#endif
lda pos+2
lsr
lsr
lsr
lsr
tay
beq pi0$
lda hex,y
and #63
#if MACH == 64 || MACH == 128
sta $0422
#endif
#if MACH == 20
sta $1010
#endif
#if MACH == 16 || MACH == 4
sta $0c22
#endif
pi0$ lda pos+2
and #$0f
tay
lda hex,y
and #63
#if MACH == 64 || MACH == 128
sta $0423
#endif
#if MACH == 20
sta $1011
#endif
#if MACH == 16 || MACH == 4
sta $0c23
#endif
lda pos+1
lsr
lsr
lsr
lsr
tay
lda hex,y
and #63
#if MACH == 64 || MACH == 128
sta $0424
#endif
#if MACH == 20
sta $1012
#endif
#if MACH == 16 || MACH == 4
sta $0c24
#endif
lda pos+1
and #$0f
tay
lda hex,y
and #63
#if MACH == 64 || MACH == 128
sta $0425
#endif
#if MACH == 20
sta $1013
#endif
#if MACH == 16 || MACH == 4
sta $0c25
#endif
noprgupd$
#endif
inc rPtr+0 ;rPtr++;
bne re$
ldx rPtr+1 ;if (rPtr == &buffer[BLOCK_SIZE]) {
inx
cpx #>(buffer+BLOCK_SIZE)
bne reh$
ldx #>buffer
reh$ stx rPtr+1 ; rPtr = &buffer[0];
re$ ;}
dec buc ;bu--;
bne bue$ ;if (!bu && eof) {
lda eof ; break;
bne break2$ ;}
bue$ jmp dataloop$
break2$
#if 1
lda speed ;if (speed!=0) {
bne bend$ ;} else
lazyflush$
#endif
lda oMaxlen
sec
sbc #3 ;if (oMaxlen >= 3) {
bcc belse$
jsr PutLz ; PutLz(fpout, oMaxlen, oMaxpos);
jmp bend$
belse$ lda oMaxlen ;} else if (oMaxlen)
beq bend$
clc
lda oChar
jsr PutFixed ; PutFixed(fpout, oChar);
bend$ ;}
sec
lda #0
jsr PutFixed ;PutFixed(fpout, 256); /* EOF */
; save uncompressed size
lda pos+0
sta usize+0
lda pos+1
sta usize+1
lda pos+2
sta usize+2
lda pos+3
sta usize+3
jmp FlushBits ;FlushBits(fpout);
#if 1
PutLzNow
; PutLz(maxlen, maxpos)
lda maxlen
sta oMaxlen
lda maxpos+0
sta oMaxpos+0
lda maxpos+1
sta oMaxpos+1
#endif
; PutLz(oMaxlen, oMaxpos)
PutLz lda oMaxlen
sec
sbc #3
sta mx3$+1
ldy #0 ; j = 0;
cpl$ cmp cplens_3,y ; while (maxlen-3 >= cplens[j]-3)
bcc cple$ ; j++;
iny
bne cpl$
cple$ tya
dey ; j--;
sec
jsr PutFixed ; PutFixed(fpout, 256+j+1);
ldx cplext,y ; if (cplext[j]) {
beq cps$
mx3$ lda #0 ; 0 means 256, 1 means 257, 2 means 258
sec
sbc cplens_3,y ; PutBits(fpout, cplext[j], (maxlen-3)-(cplens[j]-3));
jsr PutBits ; }
cps$ ldy #0 ; j = 0;
cpd$ lda oMaxpos+1 ; while (maxpos >= cpdist[j])
cmp cpdistHi,y
bcc cpde$
bne cpdn$
lda oMaxpos+0
cmp cpdistLo,y
bcc cpde$
cpdn$ iny ; j++;
bne cpd$
cpde$ dey ; j--;
tya
ldx #5
jsr PutBitsR ; PutBitsR(fpout, 5, j);
lda oMaxpos+0
sec
sbc cpdistLo,y
sta zp0
lda oMaxpos+1
sbc cpdistHi,y
sta zp1
ldx cpdext,y ; if (cpdext[j]) {
beq onee$
lda zp0 ; load in advance
cpx #9 ; if (cpdext[j] > 8) {
bcc zerto8$
ldx #8 ; PutBits(fpout, 8, maxpos-cpdist[j]);
;lda zp0
jsr PutBits
lda cpdext,y
sec
sbc #8
tax
lda zp1
;jmp PutBits ; PutBits(fpout, cpdext[j]-8, (maxpos-cpdist[j])>>8);
; jsr + rts
zerto8$ ;lda zp0 ; } else {
jmp PutBits ; PutBits(fpout, cpdext[j], maxpos-cpdist[j]);
; jsr + rts ; }
onee$ rts ; }
;==============================================================
Stored:
jsr FlushBuffer ; save the header
;-> next bytes will be at the start of the buffer
lda #$80
sta zipMode ; stored
real$ ; put fake values -- FlushBuffer will fix them
lda #0
sta flushed
jsr PutBuffer ; not last block, stored
jsr PutBuffer
jsr PutBuffer
jsr PutBuffer
jsr PutBuffer
again$ jsr GetByte
ldy ST
sty last
pha
#if MACH == 16 || MACH == 4
sei
sta $ff3f ; RAM
#endif
#if MACH == 64
sei
ldy #$34
sty 1
#endif
jsr updcrc
#if MACH == 16 || MACH == 4
sta $ff3e ; ROM
cli
#endif
#if MACH == 64
ldy #$36
sty 1
cli
#endif
pla
jsr PutBuffer
; Update uncompressed length
inc usize+0
bne 2$
inc usize+1
bne 2$
inc usize+2
bne 2$
inc usize+3
2$ bit last
bvs leave$ ; last block saved, time to leave
lda flushed
bne real$ ; PutBuffer flushed -> must insert another header
beq again$ ; Not flushed, continue adding to output buffer..
leave$ jsr FlushBuffer
lda #0
sta zipMode
rts
;--------------- Bit/byte input routines ---------------------
initbp pha
ldx #14
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
lastSector
dc.b 0
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
GetByteD64
ldx be
beq fill$
jmp read$
fill$ lda #0
sta lastSector
#if MACH == 64 || MACH == 128
lda inBurst
beq std$
lda #4
sta retry$
again$ jsr BREAD
lda status
and #15
cmp #2
bcs chke$
jmp bok$
chke$ cmp #11
bne berr$
; Disk changed -- the drive is confused
ldx #14
jsr BINQ
dec retry$
beq berr$
jmp again$
retry$ dc.b 0
#endif
std$
#if MACH == 64 || MACH == 128
clc ; screen off, but 1MHz
jsr off
#endif
ldx #14
jsr CHKOUT
lda #"U"
jsr CHROUT
lda #"1"
jsr CHROUT
lda #" "
jsr CHROUT
lda #"2" ; channel
jsr CHROUT
lda #" "
jsr CHROUT
lda #"0" ; unit
jsr CHROUT
lda inTrack ; track
jsr putval
lda inSector ; sector
jsr putval
jsr CLRCHN
ldx #14
jsr geterror ; waits until the read is finished..
cmp #0
beq noerr$
#if MACH == 64 || MACH == 128
jsr on
#endif
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
noerr$
ldx #2
jsr CHKIN
ldy #0
b2loop$ jsr CHRIN
sta inBuf,y
#if MACH == 64 || MACH == 128
sta $d020
#endif
#if MACH == 20
and #7
eor $900f
sta $900f
#endif
#if MACH == 16 || MACH == 4
sta $ff19
#endif
iny
bne b2loop$
jsr CLRCHN
lda #0
sta ST
#if MACH == 64 || MACH == 128
sec ; screen off, 2MHz
jsr off
#endif
jmp bok$
#if MACH == 64 || MACH == 128
berr$ jsr on
ldx inTrack
lda inSector
jsr BERR
#endif
bok$ inc inSector ; advance to the next sector
lda fdos
cmp #"D"
bne 1541$
lda #80+1
sta ltrack$+1 ; 1581 has 80 tracks
lda inSector
cmp #40
beq ntrack$ ; next track for 1581
bne chk$
1541$ lda #35+1 ; one-sided has 35 tracks
bit fflag
bpl onesd$
lda #2*35+1 ; double-sided has 70 tracks
onesd$ sta ltrack$+1
lda inTrack
cmp #36
bcc cmp$
sbc #35
cmp$ tax
lda inSector
cmp sectorsPerTrack-1,x
bcc sectok$
ntrack$ lda #0
sta inSector
inc inTrack
chk$ lda inTrack
ltrack$ cmp #35+1
bne sectok$
inc lastSector ; flag for EOF
sectok$
ldx #0
stx be
read$ inc be
bne ok$
lda lastSector
beq ok$
lda ST
ora #$40
sta ST
ok$ lda inBuf,x
rts
GetByte lda files
cmp #255
beq GetByteD64k$
ldx be
beq fill0$
read$ inc be
lda inBuf+0
bne 1$
cpx inBuf+1
bne 1$
lda #0
sta be
lda ST
ora #$40
sta ST
1$ lda inBuf,x
rts
GetByteD64k$
jmp GetByteD64
fill0$
#if MACH == 64 || MACH == 128
lda inMode
beq std$ ; can't use burst read -> faster to do it sequentially
lda inTrack
beq eof$
; can use burst and t&s known -> use burst read
jsr BREAD
lda status
and #15
cmp #2
bcc bok$
jsr on
ldx inTrack
lda inSector
jsr BERR
lda #0
sta inBuf+0
lda #255
sta inBuf+1
bok$ lda inBuf+0 ; copy links for next read
sta inTrack
lda inBuf+1
sta inSector
eof$ ldx #2
stx be
bne read$
#endif
std$ ldx #2
stx be
stx inBuf+0 ; Fake T&S
stx inBuf+1
lda #0
sta ST
#if MACH == 64 || MACH == 128
clc ; screen off, but 1MHz
jsr off
#endif
ldx #2
jsr CHKIN
#if MACH == 64 || MACH == 128
lda IDE64present
bpl fill$ ; IDE64 not found
tya
pha
lda #IDE64BR
ldx #254
ldy #0
jsr IDE64BlockRead
pla
tay
bcs fill$ ; Tried to read from a floppy...
inx
inx
stx be
bit ST
bvc break$
dex
bvs IDE64notall$
#endif
fill$ jsr CHRIN
ldx be
sta inBuf,x
#if MACH == 64 || MACH == 128
sta $d020
#endif
#if MACH == 20
and #7
eor $900f
sta $900f
#endif
#if MACH == 16 || MACH == 4
sta $ff19
#endif
bit ST
bvc 0$
inc be
IDE64notall$
lda #0
sta ST
sta inBuf+0 ; EOF T
stx inBuf+1 ; index of last valid byte
jmp break$
0$ inc be
bne fill$
break$ jsr CLRCHN
#if MACH == 64 || MACH == 128
sec ; screen off, 2MHz
jsr off
#endif
ldx #2
stx be
jmp read$
;--------------- Output/buffer routines ---------------------
updcrc:
; updcrc()
; (crc32_tab[((int)crc ^ cp) & 255] ^ (crc >> 8))
sty y$+1
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
y$ ldy #0
rts
; $80 0 $40 1 $20 2 $10 3 $08 4 $04 5 $02 6 $01 7
InitBits
lda #$80
sta bits
rts
bits dc.b $80
FlushBits
ldx bits
bpl 1$
rts
1$ lsr byte
lsr bits
bne 1$
;sec
ror bits ; -> $80
lda byte
jmp PutBuffer
PutBits cpx #0
bne 1$
rts
1$ lsr
ror byte
lsr bits
bne 3$
;sec
ror bits ; -> $80
pha
lda byte
jsr PutBuffer
pla
3$ dex
bne 1$
rts
maskTab dc.b 1,2,4,8,16,32,64,128
PutBitsR
sta tmp
dex
bpl 0$
rts
0$ lda maskTab,x
bit tmp
clc
beq 1$
sec
1$ ror byte
lsr bits
bne 3$
;sec
ror bits ; -> $80
lda byte
jsr PutBuffer
3$ dex
bpl 0$
rts
PutFixed ; C*256 + A
bcc lt256$
cmp #24
bcs ge24$
;256+ 0..23
ldx #7
jmp PutBitsR
ge24$ adc #167 ;256+ 24..31
ldx #8
jmp PutBitsR
lt256$ cmp #144
bcs ge144$
adc #48
ldx #8
jmp PutBitsR
ge144$ pha
ldx #1
lda #1
jsr PutBits
pla
ldx #8
jmp PutBitsR
; 70+12 cycles/byte (w/ CRC32)
PutBuffer
sty puty+1 ;4
stx putx+1
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$
outCmd sta $aaaa
inc outCmd+1 ;6
bne 2$ ;2/3
inc outCmd+2
lda outCmd+2
cmp #>outend
bne 2$
; Save buffer data buffer32k .. (outCmd)
jsr FlushBuffer
2$
puty ldy #0 ; restore Y value
putx ldx #0
rts
FlushBuffer ; Can trash A & Y, X
#if MACH == 64 || MACH == 128
clc ; screen off, but 1MHz
jsr off
#endif
lda zipMode
beq std$
; if Stored, fix the block size, its complement etc.
lda obufhi ; fix the HI parts
sta bu0$+2
sta bu1$+2
sta bu2$+2
sta bu3$+2
sta bu4$+2
bit last
bvc 5$
bu0$ inc $2000+0 ; 0 -> 1 == last block, stored
5$ lda outCmd+1
sec
sbc #5
bu1$ sta $2000+1 ; size LO
eor #255
bu2$ sta $2000+3
lda outCmd+2
sbc obufhi
bu3$ sta $2000+2 ; size HI
eor #255
bu4$ sta $2000+4
std$ ldx #3
jsr CHKOUT ; (sends LISTEN+SECOND)
lda #0
sta bTmp+0
lda obufhi
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
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
jsr InitBuffer32k
inc flushed
rts
0$ ldy #0
lda (bTmp),y
#if MACH == 64 || MACH == 128
sta $d020
jsr CHROUT
#endif
#if MACH == 20
pha
jsr CHROUT
pla
and #7
eor $900f
sta $900f
#endif
#if MACH == 16 || MACH == 4
sta $ff19
jsr CHROUT
#endif
inc bTmp+0
bne 1$
inc bTmp+1
jmp 1$
InitBuffer32k
; Init buffer pointer
lda #0
sta outCmd+1
lda obufhi
sta outCmd+2
rts
flushed dc.b 0
;--------------- Misc utility routines ---------------------
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
dec0 dc.b $00,$00,$80,$40,$a0,$10,$e8,$64,$0a,$01, $00,$00,$00, $99,$5c, $89,$8d,$a7
dec1 dc.b $ca,$e1,$96,$42,$86,$27,$03,$00,$00,$00, $00,$00,$00, $99,$8f, $41,$06,$00
dec2 dc.b $9a,$f5,$98,$0f,$01,$00,$00,$00,$00,$00, $00,$00,$00, $19,$02, $00,$00,$00
dec3 dc.b $3b,$05,$00,$00,$00,$00,$00,$00,$00,$00, $64,$0a,$01, $00,$00, $00,$00,$00
decv dc.b 0,0,0,0
decs dc.b 0
decout dc.b 0
putpct sta decbyt+1
lda #10
sta decstrt+1
lda #18
jmp putdec2
putdec sta decbyt+1
lda #0
sta decstrt+1
lda #10
putdec2 sta decend+1
stx bTmp+0
sty bTmp+1
lda #0
sta decs
sta decout
sta decv+1
sta decv+2
sta decv+3
decbyt ldy #4
dey
0$ lda (bTmp),y
sta decv,y
dey
bpl 0$
decstrt ldy #0
decend
for$ cpy #10
bne 2$
lda decout
rts
2$ ldx #0
while$ lda decv+3
cmp dec3,y
bcc breakw$ ; a < dec
bne ge$ ; a > dec
lda decv+2
cmp dec2,y
bcc breakw$ ; a < dec
bne ge$ ; a > dec
lda decv+1
cmp dec1,y
bcc breakw$ ; a < dec
bne ge$ ; a > dec
lda decv+0
cmp dec0,y
bcc breakw$ ; a < dec
ge$ inx ; a >= dec
sec
lda decv+0
sbc dec0,y
sta decv+0
lda decv+1
sbc dec1,y
sta decv+1
lda decv+2
sbc dec2,y
sta decv+2
lda decv+3
sbc dec3,y
sta decv+3
jmp while$
breakw$
cpy #9
beq put$
txa
ora decs
beq noput$
put$ txa
ora #"0"
jsr CHROUT
inc decout
inc decs
noput$ cpy #14 ; 12 for decimal, 14 for %
bne 1$
lda #"."
jsr CHROUT
inc decout
inc decs
1$ iny
jmp for$
ratioa dc.b 0,0,0,0
ratiob dc.b 0,0,0,0
ratiov dc.b 0,0,0,0
ratiosh dc.b 0
putratio
ldy #3
0$ lda csize,y
sta ratioa,y
lda usize,y
sta ratiob,y
lda #0
sta ratiov,y
dey
bpl 0$
;lda #0
sta ratiosh
while0$ ; scale divider
ldy #3
1$ lda ratiob,y
cmp ratioa,y
bcc lt$
bne breakw$
dey
bpl 1$
jmp breakw$ ; b==a
lt$ ; b < a
asl ratiob+0
rol ratiob+1
rol ratiob+2
rol ratiob+3
inc ratiosh
jmp while0$
breakw$
ldx #0
for$ ldy #3
2$ lda ratioa,y
cmp ratiob,y
bcc break2$
bne ge$
dey
bpl 2$
ge$ ; a >= b
sec
lda ratioa+0
sbc ratiob+0
sta ratioa+0
lda ratioa+1
sbc ratiob+1
sta ratioa+1
lda ratioa+2
sbc ratiob+2
sta ratioa+2
lda ratioa+3
sbc ratiob+3
sta ratioa+3
sec
break2$
rol ratiov+0
rol ratiov+1
rol ratiov+2
rol ratiov+3
asl ratioa+0
rol ratioa+1
rol ratioa+2
rol ratioa+3
inx
cpx #25 ; 25-bit result
bne for$
5$ dec ratiosh
bmi 4$
asl ratiov+0
rol ratiov+1
rol ratiov+2
rol ratiov+3
jmp 5$
4$
ldx #<ratiov
ldy #>ratiov
lda #4
jmp putpct
puthex pha
lsr
lsr
lsr
lsr ; 0..9 -> $30..$39, A..F -> $41..$46
tay
lda hex,y
jsr CHROUT
pla
and #15
tay
lda hex,y
jmp CHROUT
hex dc.b "0123456789ABCDEF"
#if MACH == 64 || MACH == 128
on
#if MACH == 64
lda $d011
ora #$10
sta $d011
lda #0 ; 1 MHz
sta $d030
#else
lda $d7 ; 40/80 columns
bne off ; 80 columns -> turn it off
sta $d030 ; 1 MHz
lda $d011
ora #$10 ; blank off
sta $d011
#endif
rts
#if MACH == 64
; NOTE: standard slow serial does not work with 2MHz in C64 mode
onemeg lda #0 ; 1MHz
sta $d030
#endif
off lda $d011
and #$ef
sta $d011
#if MACH == 64
; NOTE: standard slow serial does not work with 2MHz in C64 mode
lda #0
rol ; clc = 1MHz, sec = 2 MHz
sta $d030
#else
; NOTE: standard slow serial does work with 2MHz in C128 mode
lda #1
sta $d030
#endif
rts
#endif
putstr 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$
rts
getstr sta 0$+1 ; <buffer
sta 2$+1
stx 0$+2 ; >buffer
stx 2$+2
sty 1$+1 ; max len+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 #" "
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
#if MACH == 16 || MACH == 4
ldy #30
11$ dey
bpl 11$
#endif
jsr CHKIN
#if MACH == 16 || MACH == 4
ldy #30
12$ dey
bpl 12$
#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 #13 ; 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)
oPages dc.b 0
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 != 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
;--------------- 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 ; Double-sided flag
fdtype dc.b 0
diskName
ds.b 23
ReadDir lda #0
sta fcount
sta fdtype
#if MACH == 64 || MACH == 128
jsr prns
dc.b 13
dc.b 18,"D",146," DISK IMAGE COMPRESSION (D64/D71/D81)",13
dc.b 18,"N",146," DO NOT ARCHIVE THIS FILE",13
dc.b 18,"Y",146," ARCHIVE WITH MAXIMUM COMPRESSION",13
dc.b 18,"1",146,"-",18,"3",146," ARCHIVE WITH FASTER COMPRESSION",13
dc.b 18,"S",146," ARCHIVE STORED (NO COMPRESSION)",13
dc.b 18,"Q",146," QUIT MENU AND BEGIN CREATING ARCHIVE",13
dc.b 13, 0
#endif
; Open directory
ldx #<dir
ldy #>dir
lda #4
jsr SETNAM
; We can't use "I0" because of IDE64
; We have this hack instead.
lda #2 ; first a dummy open
ldx inDrive
ldy #0 ; open 2,8,0,"$0:*"
jsr SETLFS
jsr OPEN
lda #2
jsr CLOSE
lda #2 ; first try raw directory
ldx inDrive
ldy #2 ; open 2,8,2,"$0:*"
jsr SETLFS
jsr OPEN
ldx #14
jsr geterror
cmp #0
beq 2$
ldx #<errorStr
lda #>errorStr
ldy errorLen
jsr putstr
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 ; disk name: 142..164 165..168 unused
jsr CHKIN
jsr CHRIN ; get disk format "A" for 1541/51/71/4040 or "D" for 1581
sta fdos ; "C" for 8050
lda ST
bne quit0$
jsr CHRIN ; get double-sided flag for "A"
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 #6
is0$ jsr CHRIN
cmp #34
beq is01$
dey
bne is0$ ; skip line link, line number, reverse + "
is01$
ldy #0
is1$ jsr CHRIN ; get disk name, disk ID and dos/disk version
sta diskName,y
cmp #0
beq gotdisk$
iny
cpy #23
bne is1$
is2$ jsr CHRIN ; get 0
cmp #0
bne is2$
jmp gotdisk$
notide$ lda fdos
cmp #"D"
beq 1581$ ; no skip for 1581 & CMD Ramlink & CMD HD
cmp #"H"
beq 1581$
ldy #2 ; skip 2 bytes for 8050
cmp #"C"
beq skip0$
ldy #140 ; skip 140 bytes for 1541
skip0$ jsr CHRIN
dey
bne skip0$ ; skip disk info
1581$ ldy #0
dname$ jsr CHRIN ; get disk name, disk ID and dos/disk version
sta diskName,y
iny
cpy #23
bne dname$
lda fdos
cmp #"C"
bne nskp2$
ldy #253 ; skip 735-229=506=253*2 bytes for 8050
skip2$ jsr CHRIN
jsr CHRIN
dey
bne skip2$
; TODO: skip extra 2*254 bytes for double-sided 8050 disks
nskp2$ ldy #229 ; skip 229 bytes for 1581 and 8050, CMD Ramlink & HD
lda fdos
cmp #"A"
bne skip1$
ldy #89 ; skip 89 bytes for 1541
skip1$ jsr CHRIN
dey
bne skip1$ ; skip disk info
gotdisk$ ; display the disk name
jsr CLRCHN
lda #18
jsr CHROUT
lda #34
jsr CHROUT
ldy #0
dname2$ lda diskName,y
cpy #16
bne yes$
lda #34
yes$ jsr CHROUT
iny
cpy #23
bne dname2$
jsr prns
dc.b 146,13,0
dirloop$
ldx #2
jsr CHKIN
lda fdtype
bne ide2$
jmp noide2$
ide2$ jsr CHRIN ; skip line link
jsr CHRIN
jsr CHRIN
sta fblocks+0
lda ST
bne ret$
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$
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
bne ret$
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 notdel$
jmp dirloop$ ; skip DELeted files
notdel$
ldx #<fblocks
ldy #>fblocks
lda #2
jsr putdec
tay
0$ cpy #4
bcs 1$
lda #" "
jsr CHROUT
iny
jmp 0$
1$ ldx #" "
lda ftype
bmi closed$
ldx #"*"
closed$
txa
jsr CHROUT
lda ftype
and #7
asl
asl ; *4
clc
adc #<(ftypstr-4)
tax
lda #>(ftypstr-4)
adc #0
ldy #3
jsr putstr
lda #"<"
bit ftype
bvs locked$
lda #" "
locked$
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,"S",146," ",18,"D",146," ",18,"N",146," ",18,"Q",146,"?", 0
ack$ jsr getkey
bcs ack$
cmp #"Y"
beq this$
cmp #"0"
beq this$
cmp #"1"
beq this$
cmp #"2"
beq this$
cmp #"3"
beq this$
cmp #"S"
beq this$
cmp #3
beq quit$
cmp #"Q"
beq quit$
cmp #"D"
beq d64$
cmp #"N"
bne ack$
#if MACH != 128
ldy #37
lnoff$ lda #20 ; backspace
jsr CHROUT
dey
bpl lnoff$
#else
ldy #37
lnoff$ lda #157 ; <--
jsr CHROUT
lda #32 ; space
jsr CHROUT
lda #157 ; <--
jsr CHROUT
dey
bpl lnoff$
#endif
jmp dirloop$
d64$ lda fdos
cmp #"A" ; 1541/1571 disk
beq dok$
cmp #"D" ; 1851 disk
beq dok$
jmp ack$ ; not a disk format we support!
dok$ lda #255
sta files
quit$ lda #2
jsr CLOSE
jsr CLRCHN
jmp CR
this$ sta tmp
jsr OK_KEY
lda #0
ldy #CASIZE-1
clr$ sta (CAPtr),y ; clear
dey
bpl clr$
ldy #0
cp$ lda fname,y
sta (CAPtr),y
iny
cpy fnameln
bne cp$
lda ftype
and #7
cmp #2
beq typok$ ; If not PRG, append ",S" ",U" ",R"
lda #","
sta (CAPtr),y
iny
lda ftype
and #7
asl
asl
tax
lda ftypstr-4,x
sta (CAPtr),y
iny
typok$ tya
ldy #CA_FLen
sta (CAPtr),y ; name lenght
ldy #CA_TS
lda ftrack
sta (CAPtr),y ; start track
iny
lda fsector
sta (CAPtr),y ; start sector
lda tmp
ldy #CA_Mode
sta (CAPtr),y ; compress mode
inc files
lda CAPtr+0
clc
adc #CASIZE
sta CAPtr+0
bcc noc$
inc CAPtr+1
noc$ lda files
cmp #MAXFILES
beq toomany$
jmp dirloop$
toomany$
lda #2
jsr CLOSE
jsr CLRCHN
jsr prns
dc.b "MAXIMUM NUMBER OF FILES REACHED",13,0
rts
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 #3
bne notc$
jsr CR
sec
bcs brk$
notc$ 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
bne nok$
jsr OPEN ; reopen
clc
lda drive$+1
rts
nok$ clc
brk$ lda #0
rts
OK_KEY jsr CHROUT
CR lda #13
jmp CHROUT
d64mode dc.b 0 ; 0 = file, 4 = D64, 7 = D71, 8 = D81, $84 = one drive
d64chan dc.b "#"
inDrive dc.b 8
#if !(MACH == 64 || MACH == 128)
be dc.b 0 ; buffer index
#endif
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, $ff
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, $ff
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
;============================================================================
; Start of work space - variables
tentimes:
dc.b 0,10,20,30,40,50,60,70,80,90
#if MACH == 64 || MACH == 128
BREAD sty y$+1
ldx #$c0 ; 1581 BURST: LEXS000N L=logical t&s
lda fdos
cmp #"D"
beq 2$
; Other than 1581-format disks
ldx #$40 ; 1571 BURST: TEBS000N T=no transfer
2$ stx cmdline+2
;stx $0400
LDA inTrack
STA cmdline+3
LDA inSector
STA cmdline+4
LDA #1
STA cmdline+5
LDA #$06
STA cmdlen
ldx #14
JSR sendcmd
SEI
BIT D1ICR
LDA D2PRA
EOR #$10
STA D2PRA
1$ LDA #8
wait0$ BIT D1ICR
BEQ wait0$
LDA D1SDR
STA status
and #15
cmp #11 ; disk changed -> no data
beq 4$
LDA D2PRA
EOR #$10
STA D2PRA
ldy #0
3$ LDA #8
wait1$ BIT D1ICR
BEQ wait1$
LDA D2PRA
EOR #$10
STA D2PRA
LDA D1SDR
sta inBuf,y
#if MACH == 64 || MACH == 128
sta $d020
#endif
#if MACH == 20
and #7
eor $900f
sta $900f
#endif
INY
BNE 3$
4$ CLI
y$ ldy #0
RTS
; 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 #$10
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
oldclk
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
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
#if 1
pla
sta tmp
ldx #<tmp
ldy #>tmp
lda #1
jsr putdec
#else
lda #"T"
jsr CHROUT
pla
jsr puthex
#endif
lda #","
jsr CHROUT
#if 1
pla
sta tmp
ldx #<tmp
ldy #>tmp
lda #1
jsr putdec
#else
lda #"S"
jsr CHROUT
pla
jsr puthex
#endif
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
#endif
lhdr dc.b $50,$4b,$03,$04, $14,$00,$08,$00, $08,$00
dc.b $9f,$05,$00,$00, $00,$00,$00,$00
dc.b $00,$00,$00,$00, $00,$00,$00,$00
ghdr dc.b $50,$4b,$01,$02, $14,$00,$14,$00
dc.b $00,$00,$08,$00, $e0,$14,$69,$2d ; 9.11.2002 02:39
ehdr dc.b $50,$4b,$05,$06, $00,$00,$00,$00
inTrack dc.b 0
inSector dc.b 0
inMode dc.b 0
#if MACH != 20
inBurst dc.b 0
#endif
#if MACH == 64 || MACH == 128
IDE64present:
dc.b 0
#endif
zipMode dc.b 0 ; 0 == normal, $80 == stored
zipDrive dc.b 8
zipFile ds.b 30
zipLen dc.b 0
zipComment ds.b 36
zipCommentLen dc.b 0
errorCode dc.b 0
errorLen dc.b 0
errorStr ds.b 64
usize dc.b 0,0,0,0
csize dc.b 0,0,0,0
cstart dc.b 0,0,0,0
outSize dc.b 0,0,0,0
curlen dc.b 0
last dc.b 0
im dc.b 0,0
left dc.b 0,0
buc dc.b 0
loops dc.b 0
eof dc.b 0
skip dc.b 0
maxlen dc.b 0
maxpos dc.b 0,0
oMaxlen dc.b 0
oMaxpos dc.b 0,0
oChar dc.b 0
nChar dc.b 0
speed dc.b 0
#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+2)
sta IDE64BR
lda #>(inBuf+2)
sta IDE64BR+1
1$ sty IDE64present ; negative means IDE64 present
rts
IDEID dc.b "IDE"
CheckBurst:
lda #0
sta inBurst
sta FASTSER
lda inDrive
#if MACH == 64
jsr myLISTEN
lda #$6f
jsr mySECOND
lda #"U"
jsr myCIOUT
lda #"I"
jsr myCIOUT
lda #"+"
jsr myCIOUT
jsr myUNLSN
#else
jsr LISTEN
lda #$6f
jsr SECOND
lda #"U"
jsr CIOUT
lda #"I"
jsr CIOUT
lda #"+"
jsr CIOUT
jsr UNLSN
#endif
bit FASTSER
bvc nob$
inc inBurst
;ldx #14 ; 1570/1571 seems to need this w/ C64+burst
;jsr BINQ
;lda status
;jsr puthex
;jsr CR
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 D2PRA
and #$08
bne 1$
jsr SPOUT ; SPOUT
lda #$ff
sta D1SDR
jsr WAITSPIN ; waitSP+SPIN
txa
ldx #20
2$ dex
bne 2$
tax
#endif
1$ lda D2PRA
ora #$08
sta D2PRA ; ATNOUT hi, ATN low
myDEL sei
lda D2PRA ; CLKOUT hi, CLK low
ora #$10
sta D2PRA
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 D1ICR
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 D2PRA
cmp D2PRA
bne 3$
pha
lda D1ICR
and #$08
beq 6$
lda #$c0
sta FASTSER
6$ pla
bpl 3$
#endif
#if 0
jmp $ee8e
#else
lda D2PRA ; CLKOUT hi, CLK low
ora #$10
sta D2PRA
lda #$08
sta $a5 ; 8 bits to send
ed66 lda D2PRA
cmp D2PRA
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 D2PRA
and #$df
ora #$10
sta D2PRA ; 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 D1ICR ; clear old interrupt bits
ed9f lda D1ICR
and #$02 ; timer B expired?
bne edaf+1 ;timeout read+write
jsr eea9 ; wait settle, DATA->C
bcs ed9f ;wait for ACK
cli
rts
#endif
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 D2PRA
and #$f7
sta D2PRA ; 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
SPOUT
;lda #$7f
;sta D1ICR
lda #$00
sta $dc05
lda #$04
sta $dc04
lda $dc0e
and #$80
ora #$55
sta $dc0e
bit D1ICR
rts
WAITSPIN
0$ lda D1ICR
and #$08
beq 0$
SPIN
lda $dc0e
and #$80 ; preserve TOD mode, SP to input, timer A continuous
ora #$01
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 D2PRA ; DOUT lo, release DATA
and #$df
sta D2PRA
rts
eea0 lda D2PRA ; DOUT hi, DATA low
ora #$20
sta D2PRA
rts
eea9 lda D2PRA ; wait settle, DATA->C
cmp D2PRA
bne eea9
asl
rts
ee03 lda D2PRA
and #$f7
sta D2PRA ; 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 D2PRA ; CLKOUT lo, release CLK
and #$ef
sta D2PRA
rts
#endif
#endif
obufhi dc.b 0
files dc.b 0 ; number of files
filecnt dc.b 0
#if MACH == 128
UpdSearch:
ldx #<FarUpdSearch
lda #>FarUpdSearch
jmp farcall
ClearSearch:
ldx #<FarClearSearch
lda #>FarClearSearch
;jmp farcall
farcall stx 4 ; low byte in X, high byte in A
sta 3
lda $02de
pha
lda $ff00
sta $02de ; =return memory config
jsr JSRFAR
pla
sta $02de
cli
rts
bank1install:
; Install code to bank 1
lda #bTmp
sta $02b9 ; ZP for writebank
lda #<bank1code
sta bTmp+0
lda #>bank1code
sta bTmp+1
ldy #0
0$ lda bank1org,y
ldx #1 ; bank 1 (RAM1)
jsr WRITEBANK
iny
cpy #bank1end-bank1org
bne 0$
lda #1 ; bank 1 (RAM1)
sta 2
sei
php
pla
sta 5 ; SR
cli
rts
bank1org:
#rorg $0400
bank1code:
FarUpdSearch
; no check.. it doesn't matter if we read 1 byte off the end
updsearch$ ;if (bu > 1) {
lda arg+0 ; long off;
; unsigned short index =
asl ; ((*rPtr & (LSIZE-1)) << LSHIFT) |
asl ; (*(rPtr+1) & (LSIZE-1));
asl ; long *lPairPtr = &lPair[index];
#if LSHIFT == 4
asl ; shifting only leaves 4 bits
sta zp0
lda arg+1 ; HI
and #15 ; take only 4 bits
lsr ; shift 2 bits to LO part, because
ror zp0 ; array element is 4 bytes
lsr
ror zp0 ; leaves 2 bits in HI part
#endif
#if LSHIFT == 5
sta zp0 ; shifting only leaves 5 bits
lda arg+1
and #31 ; take only 5 bits
lsr ; shift 1 bit to LO part
ror zp0 ; leaves 3 bits in HI part
#endif
;clc ; C already clear, because zp0 is *8 (or *16)
adc #>lPair
sta zp1
lda pos+0 ; unsigned short *tmp = &bSkip[p & (BLOCK_SIZE-1)];
sta bTmp+0
lda pos+1
and #>(BLOCK_SIZE-1)
asl bTmp+0
rol
;clc ; C already clear, because BLOCK_SIZE <= 32768
adc #>bSkip
sta bTmp+1
; off = p - *lPairPtr;
; if (off < (BLOCK_SIZE-MAX_MATCH)) {
; *tmp = off;
; } else {
; *tmp = 0;
; }
ldy #0
lda pos+0
sec
sbc (zp0),y
sta off0$+1
iny
lda pos+1
sbc (zp0),y
sta off1$+1
iny
lda pos+2
sbc (zp0),y
sta off2$+1
iny
lda pos+3
sbc (zp0),y
off2$ ora #0
bne ptr0$ ;16 top bits != 0
lda off1$+1
cmp #>(BLOCK_SIZE-MAX_MATCH)
bcc ptr$ ; HI byte < --> ok!
; HI byte >=
;bne ptr0$ ; HI byte > --> not ok
;todo: compare low byte -- but it doesn't matter much..
ptr0$ lda #0 ; too far or not found
sta off0$+1
sta off1$+1
; Update search structure pointers
ptr$ ldy #0
off0$ lda #0
sta (bTmp),y ; *tmp=..
iny
off1$ lda #0
sta (bTmp),y
dey ;ldy #0
lda pos+0
sta (zp0),y ; *lPairPtr = p;
iny
lda pos+1
sta (zp0),y
iny
lda pos+2
sta (zp0),y
iny
lda pos+3
sta (zp0),y
rts
FarClearSearch:
lda #>lPair
sta clr$+2
ldx #>(lPairSize+bSkipSize)
ldy #0
tya ;lda #0
clr$ sta $aa00,y
iny
bne clr$
inc clr$+2
dex
bne clr$
rts
#rend
bank1end
#endif ; MACH==128
CA
; ds.b MAXFILES* CASIZE