mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
added iff viewer
This commit is contained in:
parent
e221d674d9
commit
3ba37df29d
277
examples/cx16/imgviewer/iffviewer.p8
Normal file
277
examples/cx16/imgviewer/iffviewer.p8
Normal file
@ -0,0 +1,277 @@
|
||||
%target cx16
|
||||
%import graphics
|
||||
%import textio
|
||||
%import diskio
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
graphics.enable_bitmap_mode()
|
||||
|
||||
if strlen(diskio.status(8)) ; trick to check if we're running on sdcard or host system shared folder
|
||||
show_pics_sdcard()
|
||||
else {
|
||||
txt.print("only works with files on\nsdcard image!\n")
|
||||
}
|
||||
|
||||
repeat {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
sub show_pics_sdcard() {
|
||||
|
||||
; load and show all *.iff pictures on the disk.
|
||||
; this only works in the emulator V38 with an sd-card image with the files on it.
|
||||
|
||||
str[20] filename_ptrs
|
||||
ubyte num_files = diskio.list_files(8, ".iff", true, &filename_ptrs, len(filename_ptrs))
|
||||
if num_files {
|
||||
while num_files {
|
||||
num_files--
|
||||
iff.show_iff_image(filename_ptrs[num_files])
|
||||
cx16.wait(120)
|
||||
}
|
||||
} else {
|
||||
txt.print("no *.iff files found\n")
|
||||
}
|
||||
}
|
||||
|
||||
sub set_palette(uword palletteptr, uword num_colors) {
|
||||
uword vera_palette_ptr = $fa00
|
||||
ubyte red
|
||||
ubyte greenblue
|
||||
|
||||
; 3 bytes per color entry, adjust color depth from 8 to 4 bits per channel.
|
||||
repeat num_colors {
|
||||
red = @(palletteptr) >> 4
|
||||
palletteptr++
|
||||
greenblue = @(palletteptr) & %11110000
|
||||
palletteptr++
|
||||
greenblue |= @(palletteptr) >> 4 ; add Blue
|
||||
palletteptr++
|
||||
cx16.vpoke(1, vera_palette_ptr, greenblue)
|
||||
vera_palette_ptr++
|
||||
cx16.vpoke(1, vera_palette_ptr, red)
|
||||
vera_palette_ptr++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
iff {
|
||||
sub show_iff_image(uword filenameptr) {
|
||||
ubyte load_ok = false
|
||||
txt.print(filenameptr)
|
||||
txt.chrout('\n')
|
||||
|
||||
uword size
|
||||
ubyte[32] buffer
|
||||
ubyte[256] cmap
|
||||
ubyte[256] cmap1
|
||||
ubyte[256] cmap2
|
||||
uword camg = 0
|
||||
str chunk_id = "????"
|
||||
uword chunk_size_hi
|
||||
uword chunk_size_lo
|
||||
uword scanline_data_ptr = progend()
|
||||
|
||||
uword width
|
||||
uword height
|
||||
ubyte num_planes
|
||||
uword num_colors
|
||||
ubyte compression
|
||||
ubyte have_cmap = false
|
||||
cmap[0] = 0
|
||||
cmap1[0] = 0
|
||||
cmap2[0] = 0
|
||||
|
||||
if diskio.f_open(8, filenameptr) {
|
||||
size = diskio.f_read(buffer, 12)
|
||||
if size==12 {
|
||||
if buffer[0]=='f' and buffer[1]=='o' and buffer[2]=='r' and buffer[3]=='m'
|
||||
and buffer[8]=='i' and buffer[9]=='l' and buffer[10]=='b' and buffer[11]=='m'{
|
||||
|
||||
while read_chunk_header() {
|
||||
if chunk_id == "bmhd" {
|
||||
void diskio.f_read(buffer, chunk_size_lo)
|
||||
width = mkword(buffer[0], buffer[1])
|
||||
height = mkword(buffer[2], buffer[3])
|
||||
num_planes = buffer[8]
|
||||
num_colors = 2 ** num_planes
|
||||
compression = buffer[10]
|
||||
}
|
||||
else if chunk_id == "camg" {
|
||||
void diskio.f_read(buffer, chunk_size_lo)
|
||||
camg = mkword(buffer[2], buffer[3])
|
||||
if camg & $0800 {
|
||||
txt.print("ham mode not supported!\n")
|
||||
break
|
||||
}
|
||||
}
|
||||
else if chunk_id == "cmap" {
|
||||
have_cmap = true
|
||||
void diskio.f_read(&cmap, chunk_size_lo)
|
||||
}
|
||||
else if chunk_id == "body" {
|
||||
txt.clear_screen()
|
||||
graphics.clear_screen(1, 0)
|
||||
if camg & $0004
|
||||
height /= 2 ; interlaced: just skip every odd scanline later
|
||||
if camg & $0080 and have_cmap
|
||||
make_ehb_palette()
|
||||
main.set_palette(&cmap, num_colors)
|
||||
if compression
|
||||
decode_rle()
|
||||
else
|
||||
decode_raw()
|
||||
load_ok = true
|
||||
break ; done after body
|
||||
}
|
||||
else {
|
||||
skip_chunk()
|
||||
}
|
||||
}
|
||||
} else
|
||||
txt.print("not an iff ilbm file!\n")
|
||||
}
|
||||
|
||||
diskio.f_close()
|
||||
}
|
||||
|
||||
if not load_ok {
|
||||
txt.print("load error!\n")
|
||||
txt.print(diskio.status(8))
|
||||
}
|
||||
|
||||
|
||||
sub read_chunk_header() -> ubyte {
|
||||
size = diskio.f_read(buffer, 8)
|
||||
if size==8 {
|
||||
chunk_id[0] = buffer[0]
|
||||
chunk_id[1] = buffer[1]
|
||||
chunk_id[2] = buffer[2]
|
||||
chunk_id[3] = buffer[3]
|
||||
chunk_size_hi = mkword(buffer[4], buffer[5])
|
||||
chunk_size_lo = mkword(buffer[6], buffer[7])
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
sub skip_chunk() {
|
||||
repeat lsb(chunk_size_hi)*8 + (chunk_size_lo >> 13)
|
||||
void diskio.f_read(scanline_data_ptr, $2000)
|
||||
|
||||
void diskio.f_read(scanline_data_ptr, chunk_size_lo & $1fff)
|
||||
}
|
||||
|
||||
sub make_ehb_palette() {
|
||||
; generate 32 additional Extra-Halfbrite colors in the cmap
|
||||
uword palletteptr = &cmap
|
||||
uword ehbptr = palletteptr + 32*3
|
||||
repeat 32 {
|
||||
@(ehbptr) = @(palletteptr)>>1
|
||||
ehbptr++
|
||||
palletteptr++
|
||||
@(ehbptr) = @(palletteptr)>>1
|
||||
ehbptr++
|
||||
palletteptr++
|
||||
@(ehbptr) = @(palletteptr)>>1
|
||||
ehbptr++
|
||||
palletteptr++
|
||||
}
|
||||
}
|
||||
|
||||
uword bitplane_stride
|
||||
uword interleave_stride
|
||||
uword offsetx
|
||||
uword offsety
|
||||
|
||||
sub start_plot() {
|
||||
bitplane_stride = width>>3
|
||||
interleave_stride = bitplane_stride * num_planes
|
||||
offsetx = 0
|
||||
offsety = 0
|
||||
if width < graphics.WIDTH
|
||||
offsetx = (graphics.WIDTH - width - 1) / 2
|
||||
if height < graphics.HEIGHT
|
||||
offsety = (graphics.HEIGHT - height - 1) / 2
|
||||
if width > graphics.WIDTH
|
||||
width = graphics.WIDTH
|
||||
if height > graphics.HEIGHT-1
|
||||
height = graphics.HEIGHT-1
|
||||
}
|
||||
|
||||
sub set_cursor(uword x, uword y) {
|
||||
cx16.r0=offsetx+x
|
||||
cx16.r1=offsety+y
|
||||
cx16.FB_cursor_position()
|
||||
}
|
||||
|
||||
sub decode_raw() {
|
||||
start_plot()
|
||||
ubyte interlaced = (camg & $0004) != 0
|
||||
uword y
|
||||
for y in 0 to height-1 {
|
||||
void diskio.f_read(scanline_data_ptr, interleave_stride)
|
||||
if interlaced
|
||||
void diskio.f_read(scanline_data_ptr, interleave_stride)
|
||||
set_cursor(0, y)
|
||||
planar_to_chunky_scanline()
|
||||
}
|
||||
}
|
||||
|
||||
sub decode_rle() {
|
||||
start_plot()
|
||||
ubyte interlaced = (camg & $0004) != 0
|
||||
uword y
|
||||
for y in 0 to height-1 {
|
||||
decode_rle_scanline()
|
||||
if interlaced
|
||||
decode_rle_scanline()
|
||||
set_cursor(0, y)
|
||||
planar_to_chunky_scanline()
|
||||
}
|
||||
}
|
||||
|
||||
sub decode_rle_scanline() {
|
||||
uword x = interleave_stride
|
||||
uword plane_ptr = scanline_data_ptr
|
||||
|
||||
while x {
|
||||
ubyte b = c64.CHRIN()
|
||||
if b > 128 {
|
||||
ubyte b2 = c64.CHRIN()
|
||||
repeat 2+(b^255) {
|
||||
@(plane_ptr) = b2
|
||||
plane_ptr++
|
||||
x--
|
||||
}
|
||||
} else if b < 128 {
|
||||
repeat b+1 {
|
||||
@(plane_ptr) = c64.CHRIN()
|
||||
plane_ptr++
|
||||
x--
|
||||
}
|
||||
} else
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
sub planar_to_chunky_scanline() {
|
||||
uword x
|
||||
for x in 0 to width-1 {
|
||||
ubyte bitnr = ((lsb(x) ^ 255) & 7) + 1
|
||||
uword pixptr = x/8 + scanline_data_ptr
|
||||
ubyte bits=0
|
||||
repeat num_planes {
|
||||
ubyte bb = @(pixptr) >> bitnr ; extract bit
|
||||
ror(bits) ; shift it into the byte
|
||||
pixptr += bitplane_stride
|
||||
}
|
||||
bits >>= 8-num_planes
|
||||
cx16.FB_set_pixel(bits)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -74,6 +74,7 @@ main {
|
||||
}
|
||||
if load_ok {
|
||||
txt.clear_screen()
|
||||
graphics.clear_screen(1, 0)
|
||||
load_ok = c64.CHRIN()
|
||||
if load_ok == 12 {
|
||||
; there is 256 colors of palette data at the end
|
||||
|
@ -19,6 +19,11 @@ main {
|
||||
txt.print_uwhex(xx, 1)
|
||||
txt.print_uwhex(progend(), 1)
|
||||
|
||||
uword scanline_data_ptr= $6000
|
||||
uword pixptr = x/8 + scanline_data_ptr ; TODO why is this code so much larger than the following:
|
||||
uword pixptr2 = scanline_data_ptr + x/8
|
||||
|
||||
|
||||
test_stack.test()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user