; 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