; file 4bit2fli.s ; ; converts 4bit format to FLI format ; By Todd S. Elliott - after heavy adaption of Arndt's svr.FlipRaw routines ; used in his GoDot program. By courtesy of Arndt Dettke. ; Make sure the makec64 routine has been called already. ; Make sure that valid 4bit data has been loaded to $4000 of the first ; available bank of SuperRAM (normally $02). ; After finishing, the FLIP raw data file will be at $3c00-7fff for further ; massaging.
; some equates, etc.
colorram = $0a ; pointer for the color info of picture data in Color RAM pixeldat = $0c ; pointer for the pixel data of picture in hi-res screen videoram = $0e ; pointer for the color info of picture data in Video Matrix fourbit'data = $15 ; word pointer to four bit data optcolor = $2f ; optimized color for color memory colorcount = $30 ; color count registers (16 bytes) histogram = $40 ; distribution of color in a card or single row histotab = $50 ; bit patterns corresponding to the color histogram sb = $89 ; start bank of exp. RAM xtemp = $8c ; .X register temporary location ytemp = $8d ; .Y register temporary location temp = $8e ; temporary two-byte zero page location for variable storage zp = $fb ; zero page variable for various purposes c64 = $3b00 ; buffer for converting the GoDot palette to 64 palette cram = $3c00 ; color ram table containing GoDot palette gdata = $4000 ; 4 bit buffer for GoDot data files
convert'4bit =* ; set up tables first
jsr setables cloop =* lda sb ; get bank - normally $02 pha .byte $ab ; PLB - set bank lda #$08 ; do 8 cardrows at a time to finish a single graphics card sta zp+2 ldx #$1f ; clear out the color distribution table s8 lda #$00 ; including colorcount and histogram (.X = $1f) - sta colorcount,x ; colorcount is a zero page location dex bpl - ldy #$03 ; do a cardrow at a time (4 bytes of 4bit data) - lda (fourbit'data),y; get 4bit data s2 and #%00001111 ; get rid of upper nybble
nop nop ; self-modifying code used here - use LSR to get rid of lower nybble ; A graphics cardrow of 4bit data contains eight values, where each ; value occupies a nybble for a total of four bytes. In the future, ; I will allow the user to select either left or right nybbles from ; the 4bit data. As it stands now, only the right nybbles are ; extracted from the 4bit data.
tax ; index the byte found there inc colorcount,x ; and count the colors found so far dey bpl - ; go through a single cardrow iny ; optimize a single color for colorram sty colorcount ; zero out the index ldx #$0f - lda colorcount,x beq + ; if empty color then skip count iny ; need to know how many individual colors were detected + dex ; go through all available c64 colors bpl - cpy #$03 ; at least 3 different colors were detected on a single cardrow? bcc + ; if not, then do not include detected colors onto the histogram ; The idea is to create a histogram containing only color counts ; from individual graphic cardrows having 3 or more different colors. ; If an individual graphic cardrow only has 1 or 2 different colors, ; then they can be included in the video matrix information. This ; way, the selection routines optimizes the best color for that ; graphics card (8 graphic cardrows) in its COLOR RAM counterpart. ldy #$03 ; do a cardrow at a time (4 bytes of 4bit data) - lda (fourbit'data),y; get 4bit data s7 and #%00001111 ; get rid of upper nybble
nop nop ; self-modifying code used here - use LSR to get rid of lower nybble
tax ; index the byte found there inc histogram,x ; and count the colors found so far dey ; histogram is also a zero page location bpl - ; go through a single cardrow + clc lda fourbit'data ; increment the source address adc #$04 ; to advance to the next cardrow (each graphics cardrow contains sta fourbit'data ; four bytes of 4bit data.) bcc + inc fourbit'data+1 ; ditto high byte + ldx #$0f ; for the colorcount clear dec zp+2 ; are we done with a single graphics card? bne s8 ; a single graphics card contains 8 graphics cardrows
; if the routine below had a .X =1 and went up to 15 instead of the other way ; around, the colors selected could be slightly different. ; According to GoDot's brightness palette, this routine is designed to select ; brighter colors for the color ram.
ldy #$00 sty optcolor ; default color is black (optcolor is a zero page location.) sty histogram ; and zero out the black color entry ldx #$0f ; go through the histogram - lda histogram,x beq + ; if empty then skip that color cmp histogram ; compare the count against the most counted color beq + ; if equal then skip that color bcc + ; if less then skip that color sta histogram ; if more then make it the new 'most counted' color stx optcolor ; and store the corresponding color entry here + dex bne - ; go through colors $01-$0f .byte $da ; PHX .byte $ab ; PLB - set bank to zero lda optcolor ; place the optimized color into corresponding colorram .byte $92,$0a ; sta (colorram) .byte $c2,$20 ; REP #$20 - turn on 16 bit memory accesses and .A inc colorram ; increment colorram offset dec zp ; are we done with 1000 graphics cards? .byte $e2,$20 ; SEP #$20 - turn on 8 bit mode beq + jmp cloop ; otherwise, go back and repeat
; set the tables again
+ jsr setables s4 lda #$08 ; do 8 card rows for a single graphics card sta zp+2 lda #$00 sta zp+3 ; hi byte set to zero s9 ldx #$0f lda #$00 - sta colorcount,x ; clear out color counts dex bpl - ldy #$03 ; get a cardrow of 4 bit data - lda sb ; normally $02 for bank activities pha .byte $ab ; PLB lda (fourbit'data),y s3 and #%00001111
nop nop ; self modifying code used here - use LSR instead for upper nybble
tax lda #$00 ; $00 for bank activities pha .byte $ab ; PLB inc colorcount,x ; count colors lda bits,y sta bitpatt,y ; create a bit pattern table lda #32 ; clear the color table as well sta coltable+1,y dey bpl - iny sty colorcount ; clear out the black color entry sty coltable ; and ditto for the background color entry lda (colorram),y ; check its corresponding color ram value beq + ; if zero then skip tax ; assign the colorram value into the color table tya sta colorcount,x ; and zero out the corresponding color entry ; Since the current graphics cardrow already has a ; corresponding color ram entry for its entire graphics ; card, do not include it in the color counting routines. stx coltable+3 ; it is the color ram's color entry
; If .X = $01 and went up to $0f, the colors selected below could be slightly ; different. As it stands now, the colors selected tend to be brighter ; according to the brightness of GoDot's color palette
+ ldx #$0f ; find most used color in a single cardrow - lda colorcount,x beq + ; if empty, move onto the next color entry cmp colorcount ; check for the highest number of a single color beq + ; if equal numbers then skip that color entry bcc + ; if less numbers then obviously skip that color entry sta colorcount ; make it the new number showing highest count of a color stx coltable+1 ; and the color entry into the color table + dex ; for videoram (upper nybble). bne - lda coltable+1 cmp #32 ; has it been filled in by a color entry? beq ++ ; if not, skip the second color check tax ; the videoram matrix can accept two different colors, one for tya ; each nybble sta colorcount,x ; clear out the color entry that was previously found ; we wouldn't want it to show up in the other nybble. sta colorcount ; and start the search for a second color ldx #$0f ; find second most used color in a single cardrow - lda colorcount,x beq + ; if empty, move onto the next color entry cmp colorcount ; check for the highest number of a single color beq + ; if equal numbers then skip that color entry bcc + ; if less numbers then obviously skip that color entry sta colorcount ; make it the new number showing highest count of a color stx coltable+2 ; and the color entry into the color table + dex ; for videoram (lower nybble). bne -
; at this point, the color table is now filled out. ; we need to insert color values into videoram matrix
+ lda coltable+2 ; get selected videoram values and #$0f ; get rid of upper nybble sta temp ; save it temporarily - temp is a zero page location lda coltable+1 asl ; move it to the upper nybble asl asl asl ora temp ; and add in the lower nybble sta (videoram),y ; both nybbles are added together and stashed into ; the videoram matrix
; we need to sort the filled out color table with lower values first in ; an ascending order.
ldx #$00 - stx ytemp ; zero page location ldy #$03 - lda coltable,x cmp coltable,y ; see which color entry is higher bcc + beq + ; if equal or less then do nothing pha lda coltable,y sta coltable,x ; otherwise, switch colors pla sta coltable,y lda bitpatt,x ; rearrange the corresponding bit patterns pha lda bitpatt,y sta bitpatt,x ; switch bitpatterns pla sta bitpatt,y + dey cpy ytemp ; go through all possible combinations to sort the color table bne - inx cpx #$03 ; are we done sorting the color table? bne --
; next we need to spread out the colors onto a histogram ; this way, colors that have to be discarded due to the VIC's color ; limitations will be assigned to their neighboring colors on ; GoDot's brightness scale.
ldy #$ff sty ytemp - iny lda coltable,y ; need to compute average of neighboring colors clc adc coltable+1,y lsr ; average the added colors cmp #16 ; have we exceeded the maximum range? bcc + ; if so, then set .A to 15 lda #15 + sta xtemp lda bitpatt,y ; store in the bit pattern ldx ytemp - inx sta histotab,x ; create a histogram table of bit patterns ; histotab is a zero page location cpx xtemp ; are we done creating a particular bit pattern on the histogram? ; xtemp is a zero page location bcc - cpx #15 ; are we done with the entire histogram? bcs + ; branch out when done stx ytemp cpy #$03 ; are we done with the sorted color table? bne --
; the bit patterns corresponding to their color values have been spread out ; over the histogram at histotab and can now be used to render the actual ; bitmap.
+ lda #$00 sta temp ldy #$03 - lda sb ; $02 - set source bank pha .byte $ab ; PLB lda (fourbit'data),y; get GoDot's four bit values s5 and #%00001111 ; get rid of upper nybble
nop nop ; self modifying code - use LSR's here to get upper nybble
tax ; index the color found lda #$00 ; set bank to $00 pha .byte $ab ; PLB lda histotab,x ; get the proper bit pattern and mask,y ; and set up the proper mask for inserting the proper bitpair ora temp ; we are creating four bitpairs onto the same byte sta temp dey bpl - lda temp ; has the byte containing graphics bitmap data iny sta (pixeldat),y ; and store it into the bitmap .byte $c2,$20 ; REP #$20; turn on 16 bit memory accesses and .A clc lda fourbit'data ; get the next 4bit datastream .byte $69,$04,$00 ; ADC #$0004 sta fourbit'data clc ; is this opcode necessary? lda videoram ; increment videoram offset by 1Kb .byte $69,$00,$04 ; ADC #$0400 sta videoram inc pixeldat ; increment the pixel bitmap offset dec zp+2 ; are we done with all 8 scanlines of a single graphics card? beq + .byte $e2,$20 ; SEP #$20 - turn on 8 bit mode jmp s9 ; and repeat through a single graphics card
+ sec lda videoram ; decrement videoram offset by $1fff .byte $e9,$ff,$1f ; SBC #$1fff sta videoram inc colorram ; increment color ram offset dec zp ; and are we done with all 1000 graphics cards? .byte $e2,$20 ; SEP #$20 - turn on 8 bit mode beq + jmp s4 ; otherwise, go back and repeat
; convert GoDot palette to 64 color palette
+ lda #$00 .byte $eb ; XBA .byte $c2,$10 ; REP #$10 turn on 16 bit registers .byte $a2,$ff,$23 ; ldx #$23ff - lda cram,x ; get individual GoDot data in buffer tay ; index it lda c64,y ; and retrieve the color 64 equivalent sta cram,x ; and stash it onto video ram matrixes dex bpl - .byte $e2,$10 ; SEP #$10 turn on 8 bit registers rts ; to exit the conversion routine
makec64 =* ; creates a table for converting the brightness palette of GoDot ; to the standard CBM color palette ldy #$00 - tya lsr lsr lsr lsr tax lda cols64,x and #$f0 sta zp tya and #$0f tax lda cols64,x and #$0f ora zp sta c64,y iny bne - rts
setables =* ; all locations are zero page
lda #$00 ; low byte sta fourbit'data sta videoram sta colorram sta pixeldat lda #>gdata sta fourbit'data+1 ; location of 4bit data sta videoram+1 lda #>cram sta colorram+1 ; location of color ram containing GoDot palette lda #$60 sta pixeldat+1 ; location of pixel data at $6000 lda #$e8 sta zp lda #$03 ; do this routine 1,000 times sta zp+1 rts
; Table to convert GoDot palette to C64 palette
cols64 =* .byte $00,$66,$99,$bb,$22,$44,$88,$cc .byte $ee,$aa,$55,$ff,$33,$77,$dd,$11
bits =* ; bit patterns .byte $00,$55,$aa,$ff; %00, %01, %10, %11
mask =* ; the mask byte .byte $c0,$30,$0c,$03; %11000000, %00110000, %00001100, %00000011
coltable =* ; color table for a single cardrow of GoDot data .byte $00,$00,$00,$00,$00
bitpatt =* ; table of corresponding bitpatterns .byte $00,$00,$00,$00
; end file 4bit2fli.s