bmx: allow palette to be loaded into memory buffer instead of vram

This commit is contained in:
Irmen de Jong 2023-11-25 13:54:44 +01:00
parent c45fbe6310
commit 45debff89f
4 changed files with 117 additions and 61 deletions

View File

@ -1,7 +1,6 @@
; Routines to load and save "BMX" files (commander X16 bitmap format) Version 1. ; Routines to load and save "BMX" files (commander X16 bitmap format) Version 1.
; Only uncompressed images are supported for now. ; Only uncompressed images are supported for now.
; BMX Specification: https://cx16forum.com/forum/viewtopic.php?t=6945 ; BMX Specification: https://cx16forum.com/forum/viewtopic.php?t=6945
; TODO: make read_palette() and write_palette() use an optional palette_buffer_ptr to store palette into system ram instead of directly into vram.
%import diskio %import diskio
@ -19,9 +18,10 @@ bmx {
ubyte palette_start ubyte palette_start
ubyte compression ubyte compression
uword error_message ; pointer to error message, or 0 if all ok uword error_message ; pointer to error message, or 0 if all ok
uword max_width = 0 ; should you want load() to check for this uword max_width = 0 ; should you want load() to check for this
uword max_height = 0 ; should you want load() to check for this uword max_height = 0 ; should you want load() to check for this
uword palette_buffer_ptr = 0 ; should you want to load the palette into main memory instead of directly into vram
sub load(ubyte drivenumber, str filename, ubyte vbank, uword vaddr, uword screen_width) -> bool { sub load(ubyte drivenumber, str filename, ubyte vbank, uword vaddr, uword screen_width) -> bool {
; Loads a BMX bitmap image and palette into vram. (and Header info into the bmx.* variables) ; Loads a BMX bitmap image and palette into vram. (and Header info into the bmx.* variables)
@ -189,11 +189,21 @@ save_end:
sub read_palette() -> bool { sub read_palette() -> bool {
; load palette data from the currently active input file ; load palette data from the currently active input file
; if palette_buffer_ptr is not 0, the palette data is read into that memory buffer,
; otherwise it is read directly into the palette in vram.
cx16.vaddr(1, $fa00+palette_start*2, 0, 1) cx16.vaddr(1, $fa00+palette_start*2, 0, 1)
cx16.r1 = palette_buffer_ptr
cx16.r0L = palette_entries cx16.r0L = palette_entries
do { do {
cx16.VERA_DATA0 = cbm.CHRIN() cx16.r2L = cbm.CHRIN()
cx16.VERA_DATA0 = cbm.CHRIN() cx16.r2H = cbm.CHRIN()
if cx16.r1 {
pokew(cx16.r1, cx16.r2) ; into memory
cx16.r1+=2
} else {
cx16.VERA_DATA0 = cx16.r2L ; into vram
cx16.VERA_DATA0 = cx16.r2H
}
cx16.r0L-- cx16.r0L--
} until cx16.r0L==0 } until cx16.r0L==0
return not cbm.READST() return not cbm.READST()

View File

@ -2,6 +2,8 @@
TODO TODO
==== ====
- optimize 6502 codegen: "for 0 to end" into repeat loops. (only for ubyte and uword, 6502 cpu)
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
... ...

View File

@ -1,8 +1,12 @@
; Viewer program for BMX image files.
; viewer program for BMX image files. ; This program shows *one* way to do it, by checking the header upfront,
; see https://cx16forum.com/forum/viewtopic.php?t=6945 ; and loading the palette into system ram first. The simplest way to load
; a BMX file is to just read everything into vram directly using a single bmx.load() call.
;
; BMX file format: see https://cx16forum.com/forum/viewtopic.php?t=6945
%import textio %import textio
%import palette
%import bmx %import bmx
%option no_sysinit %option no_sysinit
%zeropage basicsafe %zeropage basicsafe
@ -15,20 +19,29 @@ main {
txt.print("\nenter bmx image filename: ") txt.print("\nenter bmx image filename: ")
if txt.input_chars(&filename) { if txt.input_chars(&filename) {
if bmx.load_header(8, filename) { if bmx.load_header(8, filename) {
txt.print("\nwidth: ") txt.print("\nsize: ")
txt.print_uw(bmx.width) txt.print_uw(bmx.width)
txt.print("\nheight: ") txt.chrout('*')
txt.print_uw(bmx.height) txt.print_uw(bmx.height)
txt.print("\nbpp: ") txt.print(" bpp: ")
txt.print_uw(bmx.bitsperpixel) txt.print_uw(bmx.bitsperpixel)
txt.nl() txt.nl()
sys.wait(100) sys.wait(100)
; tell the loader to put the palette into system memory instead
; also make palette black at first, to hide loading (even though it is very fast)
; (you could do a soft fade-in effect with this for instance)
bmx.palette_buffer_ptr = memory("palette", 512, 0)
sys.memset(bmx.palette_buffer_ptr, 512, 0)
palette.set_rgb(bmx.palette_buffer_ptr, 256)
; switch to correct screen mode and color depth ; switch to correct screen mode and color depth
void cx16.screen_mode($80, false) void cx16.screen_mode($80, false)
cx16.VERA_L0_CONFIG = cx16.VERA_L0_CONFIG & %11111100 | bmx.vera_colordepth cx16.VERA_L0_CONFIG = cx16.VERA_L0_CONFIG & %11111100 | bmx.vera_colordepth
; actually load
; now load the image
if bmx.load(8, filename, 0, 0, 320) { if bmx.load(8, filename, 0, 0, 320) {
activate_palette()
void txt.waitkey() void txt.waitkey()
} }
} }
@ -44,4 +57,17 @@ main {
} }
} }
} }
sub activate_palette() {
; copies the pallette data from the memory buffer into vram
cx16.r1 = bmx.palette_buffer_ptr
cx16.r2L = bmx.palette_start
cx16.r3L = bmx.palette_entries
do {
palette.set_color(cx16.r2L, peekw(cx16.r1))
cx16.r1+=2
cx16.r2L++
cx16.r3L--
} until cx16.r3L==0
}
} }

View File

@ -2,61 +2,79 @@
%zeropage basicsafe %zeropage basicsafe
main { main {
ubyte counter
uword wcounter
ubyte end=10
uword wend=10
sub start() { sub start() {
cx16.r0=0
forloops()
txt.print_uw(cx16.r0)
txt.nl()
txt.print("for:\n") cx16.r0=0
for cx16.r0L in 10 to 20 { untilloops()
txt.print_ub(cx16.r0L) txt.print_uw(cx16.r0)
txt.print(" before...") txt.nl()
if cx16.r0L > 15 }
break
if cx16.r0L ==14 sub forloops() {
continue end=10
txt.print("after\n") for counter in 0 to end {
cx16.r0++
} }
txt.nl() end=0
for counter in 0 to end {
txt.print("repeat:\n") cx16.r0++
cx16.r0L=10
repeat 10 {
cx16.r0L++
txt.print_ub(cx16.r0L)
txt.print(" before...")
if cx16.r0L > 15
break
if cx16.r0L ==14
continue
txt.print("after\n")
} }
txt.nl() end=255
for counter in 0 to end {
txt.print("while:\n") cx16.r0++
cx16.r0L=10
while cx16.r0L<20 {
cx16.r0L++
txt.print_ub(cx16.r0L)
txt.print(" before...")
if cx16.r0L > 15
break
if cx16.r0L ==14
continue
txt.print("after\n")
} }
txt.nl()
txt.print("until:\n") wend=1000
cx16.r0L=10 for wcounter in 0 to wend {
do { cx16.r0++
cx16.r0L++ }
txt.print_ub(cx16.r0L) }
txt.print(" before...")
if cx16.r0L > 15 sub untilloops() {
end=10
counter = 0
repeat {
cx16.r0++
if counter==end
break break
if cx16.r0L ==14 counter++
continue }
txt.print("after\n")
} until cx16.r0L>20
txt.nl()
end=0
counter = 0
repeat {
cx16.r0++
if counter==end
break
counter++
}
counter = 0
end=255
repeat {
cx16.r0++
if counter==end
break
counter++
}
wcounter = 0
wend=1000
repeat {
cx16.r0++
if wcounter==wend
break
wcounter++
}
} }
} }