diff --git a/compiler/res/prog8lib/cx16/bmx.p8 b/compiler/res/prog8lib/cx16/bmx.p8 index 1921dd350..8c7f1cec4 100644 --- a/compiler/res/prog8lib/cx16/bmx.p8 +++ b/compiler/res/prog8lib/cx16/bmx.p8 @@ -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) { diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index daa7b332b..fdb26c378 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -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 `_ . +There's also the "showbmx" example to look at. emudbg (cx16 only) diff --git a/examples/test.p8 b/examples/test.p8 index b739e92db..23abac320 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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() } }