bmx support to save partial screens ('stamps')

This commit is contained in:
Irmen de Jong 2023-11-30 22:12:13 +01:00
parent b58a3ba1bb
commit 992732f2cb
3 changed files with 59 additions and 43 deletions

View File

@ -2,9 +2,6 @@
; Only uncompressed images are supported for now.
; BMX Specification: https://cx16forum.com/forum/viewtopic.php?t=6945
; TODO: ability to save "stamps" , bitmaps that are only a region of the screen.
; TODO: ability to just load the palette from a BMX file
%import diskio
bmx {
@ -106,23 +103,45 @@ bmx {
return error_message==0
}
sub save(ubyte drivenumber, str filename, ubyte vbank, uword vaddr) -> bool {
sub continue_load_only_palette() -> bool {
; Continues loading the palette but not the bitmap data from the opened BMX file.
; You can set palette_buffer_ptr if you want the palette buffered rather than directly into vram.
; Returns true if all is ok, false otherwise + error_message will be set.
; Afterwards the file is closed and you can no longer read additional data from it!
error_message = 0
diskio.reset_read_channel()
if not read_palette()
error_message = "palette error"
close()
return error_message==0
}
sub save(ubyte drivenumber, str filename, ubyte vbank, uword vaddr, uword screenwidth) -> bool {
; Save bitmap and palette data from vram into a BMX file.
; First you must have set all bmx.* variables to the correct values! (like width, height..)
; Parameters:
; drive number and filename to save to,
; vram bank and address of the bitmap data to save.
; vram bank and address of the bitmap data to save,
; and optionally the screen width if you want to save a "stamp" that's smaller than the screen.
; If you're saving the whole screen width, you can leave screenwidth at 0.
; Returns: success status. If false, error_message points to the error message string.
; TODO: how to save bitmaps that are not the full visible screen width (non-contiguous scanlines)?
error_message = 0
if compression {
error_message = "compression not supported"
return false
}
error_message = 0
if width!=320 and width!=640 {
error_message = "width not 320 or 640"
goto save_end
if screenwidth==0 {
if width!=320 and width!=640 {
error_message = "width not 320 or 640"
return false
}
} else {
if width>screenwidth {
error_message = "image too large"
return false
}
}
old_drivenumber = diskio.drivenumber
diskio.drivenumber = drivenumber
if diskio.f_open_w(filename) {
@ -134,7 +153,7 @@ bmx {
diskio.reset_write_channel()
if write_header() {
if write_palette() {
if not write_bitmap(vbank, vaddr)
if not write_bitmap(vbank, vaddr, screenwidth)
error_message = "bitmap error"
} else
error_message = "palette error"
@ -257,12 +276,19 @@ save_end:
return not cbm.READST()
}
sub write_bitmap(ubyte vbank, uword vaddr) -> bool {
; save contiguous bitmap from vram to the currently active output file
sub write_bitmap(ubyte vbank, uword vaddr, uword screenwidth) -> bool {
; screenwidth=0: save contiguous bitmap from vram to the currently active output file
; screenwidth>0: save "stamp" bitmap from vram to the currently active output file
cx16.vaddr(vbank, vaddr, 0, 1)
cx16.r3 = bytes_per_scanline(width)
repeat height
cx16.r3 = bytes_per_scanline(width) ; num bytes per image scanline
cx16.r2 = 0
if screenwidth
cx16.r2 = bytes_per_scanline(screenwidth-width) ; num bytes padding per screen scanline
repeat height {
write_scanline(cx16.r3)
repeat cx16.r2
cx16.r0L = cx16.VERA_DATA0
}
return not cbm.READST()
sub write_scanline(uword size) {

View File

@ -487,23 +487,14 @@ bmx (cx16 only)
----------------
Routines to load and save "BMX" files, the CommanderX16 bitmap file format.
Specification available here: https://cx16forum.com/forum/viewtopic.php?t=6945
Only *uncompressed* bitmaps are supported in this library.
Only *uncompressed* bitmaps are supported in this library for now.
The routines are designed to be fast and bulk load/save the data directly into or from vram,
without the need to buffer something in main memory.
Here is the load routine:
``load(ubyte drivenumber, str filename, ubyte vbank, uword vaddr)``
Loads a BMX bitmap image and palette into vram. (and Header info into the bmx.* variables)
Parameters:
the drive number and filename to load,
and the vram bank and address where the bitmap data should go.
You can set the ``bmx.max_width`` and ``bmx.max_height`` variables first, if you want this routine to check those.
Returns: success status. If false, ``bmx.error_message`` points to the error message string.
For details about the other routines such as ``save``, have a look at
For details about what routines are available, have a look at
the `source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/cx16/bmx.p8>`_ .
There's also the "showbmx" example to look at.
emudbg (cx16 only)

View File

@ -1,25 +1,24 @@
%import textio
%import floats
%import string
%import bmx
%zeropage basicsafe
%option no_sysinit
main {
sub start() {
str buffer = "???????????????????????????"
repeat {
txt.print("enter number: ")
void txt.input_chars(buffer)
txt.print("\nprog8's parse_f: ")
float value = floats.parse_f(buffer)
floats.print_f(value)
; floats.VAL_1 is defined as:
; romsub $fe09 = VAL_1(uword string @XY, ubyte length @A) clobbers(A,X,Y) -> float @FAC1
txt.print("\nrom val_1: ")
value = floats.VAL_1(buffer, string.length(buffer))
floats.print_f(value)
txt.nl()
bmx.palette_buffer_ptr = memory("palette", 512, 0)
if bmx.open(8, "desertfish.bmx") {
if bmx.continue_load(0,0) {
uword offset = 10*320 + 100
bmx.width = 100
bmx.height = 150
if bmx.save(8, "@:stamp.bmx", 0, offset, 320) {
txt.print("save stamp ok\n")
return
}
}
}
txt.print("error: ")
txt.print(bmx.error_message)
txt.nl()
}
}