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