; Create 9-bit output routine. ; This routine converts 9-bit data out of ordinary 8-bit data. ; At a first glance, this looks like a useless subroutine. However, this ; routine illustrates that the Commodore 8-bit computers are truly 9-bit ; computers, with emphasis on bit-banging routines. But there is a more ; practical matter- This can be used for compression routines. Let's examine a ; typical scenario confronting a compression program, that of recognizing ; whether the input stream contains data bytes or special compressed bytes. ; Ordinarily, data can come in any form from 0 to 255. So, how can a ; compression program know bytes in the input stream is data and which is not? ; Simple- enlarge the input stream to 9 bits at a time. Thus, bits 0-7 contain ; the usual and ordinary data with bit 8 containing a zero, signifying that ; this is ordinary data, etc. But, if bit 9 is set to one, then this signals ; the compression routine that the following bits are compressed data, and it ; acts accordingly. This is not unusual to CBM computers- Witness the GCR ; method used in the 1541 drives. The 1541 had to devise a system of ; differentating data bytes and that of special header located all over the ; disk. Thus, the GCR format has 10 bits to every ordinary 8 bits of true data. ; Anyway, enjoy. Feel free to use this subroutine without any attribution. ; By Todd S. Elliott - 1997. ; email addy: telliott@ubmail.ubalt.edu ; local equates. maskflag = $ff ; Flag to indicate how many bits need to be manipulated. ; Range is from zero to seven. ; This is to create a 'mask' to weed out useless bits. zp1 = $fa ; zero page buffer one. zp2 = $fc ; zero page buffer two. inbuffer = 14336 ; Input buffer containing ordinary 8-bit data. outbuffr = 16384 ; Output buffer containing 9-bit data. ; These buffer addresses are guidelines only. Feel free to ; improvise. ; Buddy assembler format. *= 8000 .dvo 10 .obj "convert9" .dis convert8to9 =* ; initalize pointers, etc. lda #$07 sta maskflag; initialize the maskflag to seven. lda #$00 sta ytemp; set .Y registers. sta ytemp+1 sta zp1 sta zp2 lda #>inbuffer sta zp1+1; store inbuffer in zero page buffer one. lda #>outbuffr sta zp2+1; ditto for outbuffr in zero page buffer two. - ldy ytemp lda (zp2),y; retrieve a single byte from outbuffr. sta temp; store it for later massaging. sty ytemp; save .Y register for later use. ldy ytemp+1 lda (zp1),y; retreive a single byte from inbuffer sta temp+1; store it for later massaging. inc ytemp+1; save .Y register for later use. ldy maskflag - lsr temp; manipulate the outbuffr content to the right. dey; and eliminate useless bits. bpl - asl temp; shift the value in temp to the left with an empty bit. ; Important - This adds the 9th bit! ldy maskflag; reset the .Y register again to the same value. beq + - asl temp+1; manipulate the inbuffer content to the left with carry. rol temp; use the carry to manipulate the outbuffr with the inbuffer contents. dey bne -; very important (BNE) not (BPL). this is to decrement bit shifting by ; one bit char. ; The variable area, TEMP, holds the 9-bit value field of which it is banged ; into shape by using the ASL's and the ROL's, with the carry flag doing heavy ; duty lifting. + ldy ytemp; retrieve old .Y register value. lda temp sta (zp2),y; store the modified value back to outbuffr. iny beq ++ sty ytemp; save it again for re-loop. lda temp+1 sta (zp2),y; store the remaining offset back to outbuffr. dec maskflag; Decrement the mask counter. bpl + lda #$07 sta maskflag; if depleted, then reset it to its original value, seven. inc ytemp beq ++; if zero flag is set, then abort. + jmp --- ; This routine is somewhat limited- It only reads in around 227 characters, ; which is equal to 256 bytes containing 9-bit data. You would have to add an ; extra index register, possibly .X and then update the values in the zp ; variables whenever a page boundary is crossed, so that more characters can ; be converted. Ah, if you're reading this and nodding, you know what to do. :) / rts; and exit to oblivion. ; The opposite routine, this converts 9 bits back to 8 bits. convert9to8 =* ; initalize pointers, etc. lda #$00 sta maskflag; initialize the maskflag to seven. sta ytemp; set .Y registers. sta ytemp+1 sta zp1 sta zp2 lda #>inbuffer sta zp1+1; store inbuffer in zero page buffer one. lda #>outbuffr sta zp2+1; ditto for outbuffr in zero page buffer two. - ldy ytemp lda (zp2),y sta temp iny beq -- lda (zp2),y; get all nine bits. sta temp+1 sty ytemp ldy maskflag - asl temp+1 rol temp; acquire 8 bits dey bpl - ; What we do have now is that there is a 8-bit value in TEMP and the carry bit ; holds the 9th bit for later processing at programmer's discretion. ldy ytemp+1 lda temp sta (zp1),y; and store it in some location. (14336 here.) inc ytemp+1 inc maskflag lda maskflag cmp #$08; have we reached the end of the 9-bit cycle? bne -- lda #$00; reset the counter to zero. sta maskflag inc ytemp beq --- jmp -- ; program variables. ytemp =* temp =*+2 ; we are basically done with the conversion routine. We would need to go back, ; etc. Feel free to customize to your satisfaction. ; End Convert8to9 file.