;*** KAR file decoder version 1.00 - by Craig Bruce - 05-Mar-94 ;unkar [-help] file ... ;Kevin's ARchiver format, created by Kevin Phillips and Craig Bruce, 1991 ;line length limited to 250 characters .seq "acehead.s" .org aceAppAddress .obj "@0:unkar" jmp main .byte aceID1,aceID2,aceID3 .byte 64,0 ;** stack,reserved ;*** global declarations chrQUOTE = $22 arg = 2 ;(2) ;current argument number name = 4 ;(2) ;name of file being bcoded inBufPtr = 6 ;(2) ;next char to extract from inBuf inBufCount = 8 ;(2) ;number of valid chars in inBuf inBufLen = 10 ;(2) ;total size of input buffer scanVal = 12 ;(4) ;scanNum: value returned scanSave = 16 ;(4) ;scanNum: save for *4 to *5 scanDigit = 20 ;(1) ;scanNum: new digit scanTemp = 21 ;(1) ;scanNum: temp scanIndex = 22 ;(1) ;scanNum: scanning index scanAnything = 23 ;(1) ;scanNum: flag for if anything scanned fileCount = 24 ;(4) ;files left in current archive lineCount = 28 ;(4) ;lines left in current file inFile = 32 ;(1) ;input file descriptor outFile = 33 ;(1) ;output file descriptor work = 112 ;(16);temporary work area, lowest level ;===main=== main = * ;** check for large enough TPA sec lda #bssEnd sbc aceMemTop+1 bcs + jmp mainInit + lda #tpaMsg jsr eputs die = * lda #1 ldx #0 jmp aceProcExit tpaMsg = * .asc "Insufficient program space to run more" .byte chrCR,0 usage = * lda #usageMsg jsr eputs jmp die usageMsg = * .asc "usage: unkar [-help] file ..." .byte chrCR,0 mainInit = * lda #0 sta arg+0 sta arg+1 mainNext = * jsr checkStop inc arg+0 bne + inc arg+1 + lda arg+0 ldy arg+1 jsr getarg beq mainExit lda zp+0 ldy zp+1 sta name+0 sty name+1 ldy #0 lda (zp),y cmp #"-" bne + jmp usage + jsr unkar jmp mainNext mainExit = * rts checkStop = * jsr aceConStopkey bcs + rts + lda #stoppedMsg jsr eputs jmp die stoppedMsg = * .asc "" .byte chrCR,0 unkar = * jsr echo ;** open file lda name+0 ldy name+1 sta zp+0 sty zp+1 lda #"r" jsr open bcc + ;xx open error rts + sta inFile jsr initGetByte ;** decode file jsr unkarBody ;** close file lda inFile jsr close rts invalidFormatMsg = * .asc ": invalid KAR file format" .byte chrCR,0 invalidFormat = * lda name+0 ldy name+1 jsr eputs lda #invalidFormatMsg jsr eputs rts unkarBody = * ;** get the file count jsr getline bcs invalidFormat ldx #fileCount jsr getnum bcs invalidFormat unkarNextFile = * jsr checkStop lda fileCount+0 ora fileCount+1 ora fileCount+2 ora fileCount+3 bne + rts ;** get filename + jsr getline bcs invalidFormat jsr echoExtract lda #line sta zp+0 sty zp+1 lda #"w" jsr open bcc + ;xx check for file exists lda #line jsr eputs lda #cannotOpenMsg jsr eputs rts + sta outFile ;** get file line count jsr getline bcs invalidFormatClose ldx #lineCount jsr getnum bcc unkarNextLine invalidFormatClose = * lda outFile jsr close jmp invalidFormat unkarNextLine = * lda lineCount+0 ora lineCount+1 ora lineCount+2 ora lineCount+3 bne + lda outFile jsr close ldx #fileCount jsr dec32 jmp unkarNextFile ;** copy lines of file + jsr getline bcs invalidFormatClose lda #chrCR sta line,y iny lda #line sta zp+0 stx zp+1 tya ldy #0 ldx outFile jsr write ldx #lineCount jsr dec32 jmp unkarNextLine cannotOpenMsg = * .asc ": cannot open for writing" .byte chrCR,0 dec32 = * clc ldy #4 - lda 0,x sbc #0 sta 0,x inx dey bne - rts echo = * lda #echoMsg1 jsr eputs lda name+0 ldy name+1 jsr eputs lda #echoMsg2 jmp eputs echoMsg1 = * .asc "unkaring file " .byte chrQUOTE,0 echoMsg2 = * .byte chrQUOTE,chrCR,0 echoExtract = * lda #echoExtractMsg1 jsr eputs lda #line jsr eputs lda #echoExtractMsg2 jmp eputs echoExtractMsg1 = * .asc "extracting file " .byte chrQUOTE,0 echoExtractMsg2 = * .byte chrQUOTE,chrCR,0 ;=== standard library === puts = * ldx #stdout fputs = * sta zp+0 sty zp+1 ldy #$ff - iny lda (zp),y bne - tya ldy #0 jmp write eputs = * ldx #stderr jmp fputs eputchar = * ldx #stderr jmp putc putchar = * ldx #stdout putc = * sta putcBuffer lda #putcBuffer sta zp+0 sty zp+1 lda #1 ldy #0 jmp write putcBuffer .buf 1 getarg = * sty zp+1 asl sta zp+0 rol zp+1 clc lda aceArgv+0 adc zp+0 sta zp+0 lda aceArgv+1 adc zp+1 sta zp+1 ldy #0 lda (zp),y tax iny lda (zp),y stx zp+0 sta zp+1 ora zp+0 rts getline = * ;( ) : line, .Y=lineLen, .CS=eof ldy #0 - sty work+0 jsr getByte bcc + rts + ldy work+0 sta line,y iny cpy #254 bcs getlineSkip cmp #chrCR bne - dey getlineExit = * lda #0 sta line,y clc rts getlineSkip = * lda #getlineTooLongMsg jsr eputs - jsr getByte bcc + rts + cmp #chrCR bne - ldy #254 jmp getlineExit getlineTooLongMsg = * .asc "unkar: line too long, truncating" .byte chrCR,0 initGetByte = * lda #0 sta inBufCount+0 sta inBufCount+1 sec lda aceMemTop+0 sbc #inBuf sta inBufLen+1 rts getByte = * lda inBufCount+0 ora inBufCount+1 beq getByteFillBuf ldy #0 lda (inBufPtr),y inc inBufPtr+0 bne + inc inBufPtr+1 + ldx inBufCount+0 bne + dec inBufCount+1 + dec inBufCount+0 clc rts getByteFillBuf = * jsr checkStop lda #inBuf sta zp+0 sty zp+1 sta inBufPtr+0 sty inBufPtr+1 lda inBufLen+0 ldy inBufLen+1 ldx inFile jsr read beq + bcs + sta inBufCount+0 sty inBufCount+1 jmp getByte + sec rts scanNum = * ;( (zp)=num, .Y=inLineIndex ) : .Y=scan, [scanVal]=num, .CS=err ldx #3 lda #0 - sta scanVal,x dex bpl - lda #0 sta scanAnything - lda (zp),y cmp #" " bne scanNumNext iny bne - sec rts scanNumNext = * lda (zp),y cmp #"0" bcc + cmp #"9"+1 bcc ++ + lda scanAnything beq scanError clc rts + and #$0f sta scanDigit lda #$ff sta scanAnything ;** times ten sty scanTemp ldx #3 - lda scanVal,x sta scanSave,x dex bpl - lda #2 sta scanIndex - clc ldy #4 ldx #0 - rol scanVal,x inx dey bne - bcs scanError dec scanIndex bne -- clc ldy #4 ldx #0 - lda scanVal,x adc scanSave,x sta scanVal,x inx dey bne - bcs scanError clc ldy #4 ldx #0 - rol scanVal,x inx dey bne - bcs scanError clc ldy #4 ldx #0 lda scanDigit - adc scanVal,x sta scanVal,x lda #0 inx dey bne - bcs scanError ldy scanTemp iny beq scanError jmp scanNumNext scanError = * sec rts getnum = * ;( line, .X=zpaddr ) : .CS=err stx work+0 lda #line sta zp+0 sty zp+1 ldy #0 jsr scanNum bcc + rts + ldy #0 ldx work+0 - lda scanVal,y sta 0,x inx iny cpy #4 bcc - clc rts ;===bss=== bss = * line = bss+0 inBuf = line+256 bssEnd = inBuf+64