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