mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
bmx can load "stamps"
This commit is contained in:
parent
278e2f5605
commit
5d9caef45f
@ -2,6 +2,12 @@
|
||||
; Only uncompressed images, of width 320 or 640, are supported for now.
|
||||
; BMX Specification: https://cx16forum.com/forum/viewtopic.php?t=6945
|
||||
|
||||
|
||||
; TODO: refactor loading: bmx.open() - reads header . bmx.continue_load() - reads the palette+bitmap. bmx.close() -cleanup bmx.save() stays the same
|
||||
; TODO: ability to save "stamps" , bitmaps that are only a region of the screen.
|
||||
; TODO: load 4bpp/2bpp/1bpp images
|
||||
; TODO: save 4bpp/2bpp/1bpp images
|
||||
|
||||
%import diskio
|
||||
|
||||
bmx {
|
||||
@ -47,7 +53,8 @@ bmx {
|
||||
goto load_end
|
||||
}
|
||||
if width!=320 and width!=640 {
|
||||
error_message = "width not 320 or 640" ; TODO: deal with other widths
|
||||
; note: use load_stamp() to read other sizes
|
||||
error_message = "width not 320 or 640"
|
||||
goto load_end
|
||||
}
|
||||
if compression {
|
||||
@ -66,6 +73,57 @@ bmx {
|
||||
} else
|
||||
error_message = diskio.status()
|
||||
|
||||
load_end:
|
||||
diskio.f_close()
|
||||
diskio.drivenumber = old_drivenumber
|
||||
return error_message==0
|
||||
}
|
||||
|
||||
sub load_stamp(ubyte drivenumber, str filename, ubyte vbank, uword vaddr, uword screenwidth) -> bool {
|
||||
; Loads a BMX bitmap "stamp" image and palette into vram. (and Header info into the bmx.* variables)
|
||||
; "Stamp" means: load an image that is smaller than the screen (so we need to pad around it)
|
||||
; Parameters:
|
||||
; the drive number and filename to load,
|
||||
; and the vram bank and address where the bitmap data should go,
|
||||
; finally the screen width that the stamp image is loaded into.
|
||||
; You can set the max_width and max_height variables first, if you want this routine to check those.
|
||||
; Note: does not change vera screen mode or colordepth! You have to do that yourself!
|
||||
; Returns: success status. If false, error_message points to the error message string.
|
||||
error_message = 0
|
||||
ubyte old_drivenumber = diskio.drivenumber
|
||||
diskio.drivenumber = drivenumber
|
||||
if diskio.f_open(filename) {
|
||||
diskio.reset_read_channel()
|
||||
if read_header() {
|
||||
if parse_header() {
|
||||
if max_width and width>max_width {
|
||||
error_message = "image too large"
|
||||
goto load_end
|
||||
}
|
||||
if max_height and height>max_height {
|
||||
error_message = "image too large"
|
||||
goto load_end
|
||||
}
|
||||
if width>screenwidth {
|
||||
error_message = "image too large"
|
||||
goto load_end
|
||||
}
|
||||
if compression {
|
||||
error_message = "compression not supported"
|
||||
goto load_end
|
||||
}
|
||||
if read_palette() {
|
||||
if not read_bitmap_padded(vbank, vaddr, screenwidth)
|
||||
error_message = "bitmap error"
|
||||
} else
|
||||
error_message = "palette error"
|
||||
} else
|
||||
error_message = "invalid bmx file"
|
||||
} else
|
||||
error_message = "invalid bmx file"
|
||||
} else
|
||||
error_message = diskio.status()
|
||||
|
||||
load_end:
|
||||
diskio.f_close()
|
||||
diskio.drivenumber = old_drivenumber
|
||||
@ -129,14 +187,14 @@ load_end:
|
||||
; drive number and filename to save to,
|
||||
; vram bank and address of the bitmap data to save.
|
||||
; 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)
|
||||
; TODO: how to save bitmaps that are not the full visible screen width (non-contiguous scanlines)?
|
||||
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" ; TODO: deal with other widths
|
||||
error_message = "width not 320 or 640"
|
||||
goto save_end
|
||||
}
|
||||
ubyte old_drivenumber = diskio.drivenumber
|
||||
@ -211,27 +269,39 @@ save_end:
|
||||
return cbm.READST()==0 or cbm.READST()&$40 ; no error or eof?
|
||||
}
|
||||
|
||||
sub read_bitmap_padded(ubyte vbank, uword vaddr, uword screenwidth) -> bool {
|
||||
; load bitmap "stamp" into vram from the currently active input file
|
||||
cx16.r3 = bytes_per_scanline(width) ; num bytes per image scanline
|
||||
cx16.r2 = bytes_per_scanline(screenwidth) ; num bytes per screen scanline
|
||||
repeat height {
|
||||
cx16.vaddr(vbank, vaddr, 0, 1)
|
||||
read_scanline(cx16.r3)
|
||||
vaddr += cx16.r2
|
||||
if_cs
|
||||
vbank++
|
||||
}
|
||||
return cbm.READST()==0 or cbm.READST()&$40 ; no error or eof?
|
||||
}
|
||||
|
||||
sub read_bitmap(ubyte vbank, uword vaddr) -> bool {
|
||||
; load contiguous bitmap into vram from the currently active input file
|
||||
; TODO how to deal with bitmaps that are smaller than the screen?
|
||||
cx16.vaddr(vbank, vaddr, 0, 1)
|
||||
cx16.r3 = bytes_per_scanline(width)
|
||||
cx16.vaddr(vbank, vaddr, 0, 1)
|
||||
repeat height
|
||||
read_scanline(cx16.r3)
|
||||
return cbm.READST()==0 or cbm.READST()&$40 ; no error or eof?
|
||||
}
|
||||
|
||||
sub read_scanline(uword size) {
|
||||
while size {
|
||||
cx16.r0 = cx16.MACPTR(min(255, size) as ubyte, &cx16.VERA_DATA0, true)
|
||||
if_cs {
|
||||
; no MACPTR support
|
||||
repeat size
|
||||
cx16.VERA_DATA0 = cbm.CHRIN()
|
||||
return
|
||||
}
|
||||
size -= cx16.r0
|
||||
sub read_scanline(uword size) {
|
||||
while size {
|
||||
cx16.r0 = cx16.MACPTR(min(255, size) as ubyte, &cx16.VERA_DATA0, true)
|
||||
if_cs {
|
||||
; no MACPTR support
|
||||
repeat size
|
||||
cx16.VERA_DATA0 = cbm.CHRIN()
|
||||
return
|
||||
}
|
||||
return
|
||||
size -= cx16.r0
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +338,6 @@ save_end:
|
||||
|
||||
sub write_bitmap(ubyte vbank, uword vaddr) -> bool {
|
||||
; save contiguous bitmap from vram to the currently active output file
|
||||
; TODO how to deal with bitmaps that are smaller than the screen
|
||||
cx16.vaddr(vbank, vaddr, 0, 1)
|
||||
cx16.r3 = bytes_per_scanline(width)
|
||||
repeat height
|
||||
@ -293,14 +362,8 @@ save_end:
|
||||
}
|
||||
|
||||
sub bytes_per_scanline(uword w) -> uword {
|
||||
when bitsperpixel {
|
||||
1 -> cx16.r0L = 3
|
||||
2 -> cx16.r0L = 2
|
||||
4 -> cx16.r0L = 1
|
||||
8 -> return w
|
||||
else -> return 0
|
||||
}
|
||||
return w >> cx16.r0L
|
||||
ubyte[4] shifts = [3,2,1,0]
|
||||
return w >> shifts[vera_colordepth]
|
||||
}
|
||||
|
||||
sub parse_header() -> bool {
|
||||
|
@ -281,7 +281,8 @@ close_end:
|
||||
; note: only a single iteration loop can be active at a time!
|
||||
; Returns true if the file is successfully opened and readable.
|
||||
; No need to check status(), unlike f_open_w() !
|
||||
; NOTE: the default input isn't yet set to this logical file, you can use reset_read_channel() to do this!
|
||||
; NOTE: the default input isn't yet set to this logical file, you must use reset_read_channel() to do this,
|
||||
; if you're going to read from it yourself instead of using f_read()!
|
||||
f_close()
|
||||
|
||||
cbm.SETNAM(string.length(filenameptr), filenameptr)
|
||||
|
@ -273,7 +273,8 @@ close_end:
|
||||
; note: only a single iteration loop can be active at a time!
|
||||
; Returns true if the file is successfully opened and readable.
|
||||
; No need to check status(), unlike f_open_w() !
|
||||
; NOTE: the default input isn't yet set to this logical file, you can use reset_read_channel() to do this!
|
||||
; NOTE: the default input isn't yet set to this logical file, you must use reset_read_channel() to do this,
|
||||
; if you're going to read from it yourself instead of using f_read()!
|
||||
f_close()
|
||||
|
||||
cbm.SETNAM(string.length(filenameptr), filenameptr)
|
||||
|
@ -18,6 +18,7 @@ main {
|
||||
repeat {
|
||||
txt.print("\nenter bmx image filename: ")
|
||||
if txt.input_chars(&filename) {
|
||||
|
||||
if bmx.load_header(8, filename) {
|
||||
txt.print("\nsize: ")
|
||||
txt.print_uw(bmx.width)
|
||||
@ -34,15 +35,36 @@ main {
|
||||
bmx.palette_buffer_ptr = memory("palette", 512, 0)
|
||||
sys.memset(bmx.palette_buffer_ptr, 512, 0)
|
||||
palette.set_rgb(bmx.palette_buffer_ptr, 256)
|
||||
bmx.max_width = 320
|
||||
bmx.max_height = 240
|
||||
|
||||
; switch to correct screen mode and color depth
|
||||
void cx16.screen_mode($80, false)
|
||||
; switch to bitmap screen mode and color depth: 320*240
|
||||
void cx16.screen_mode($80, false) ; we're lazy and just use a kernal routine to set up the basics
|
||||
cx16.VERA_L0_CONFIG = cx16.VERA_L0_CONFIG & %11111100 | bmx.vera_colordepth
|
||||
|
||||
; now load the image
|
||||
if bmx.load(8, filename, 0, 0) {
|
||||
activate_palette()
|
||||
void txt.waitkey()
|
||||
if bmx.width==320 {
|
||||
; can use the fast, full-screen load routine
|
||||
if bmx.load(8, filename, 0, 0) {
|
||||
if bmx.height<240 {
|
||||
; fill the remaining bottom part of the screen
|
||||
cx16.GRAPH_set_colors(bmx.border, bmx.border, 99)
|
||||
cx16.GRAPH_draw_rect(0, bmx.height, 320, 240-bmx.height, 0, true)
|
||||
}
|
||||
activate_palette()
|
||||
void txt.waitkey()
|
||||
}
|
||||
} else {
|
||||
; clear the screen with the border color
|
||||
cx16.GRAPH_set_colors(0, 0, bmx.border)
|
||||
cx16.GRAPH_clear()
|
||||
; need to use the slower load routine that does padding
|
||||
; center the image on the screen nicely
|
||||
uword offset = (320-bmx.width)/2 + (240-bmx.height)/2*320
|
||||
if bmx.load_stamp(8, filename, 0, offset, 320) {
|
||||
activate_palette()
|
||||
void txt.waitkey()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +82,7 @@ main {
|
||||
|
||||
sub activate_palette() {
|
||||
; copies the pallette data from the memory buffer into vram
|
||||
cx16.VERA_DC_BORDER = bmx.border
|
||||
cx16.r1 = bmx.palette_buffer_ptr
|
||||
cx16.r2L = bmx.palette_start
|
||||
cx16.r3L = bmx.palette_entries
|
||||
|
@ -13,6 +13,9 @@ main {
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user