mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
moved cx16 imageviewer into its own git repo. Version 6.0.
This commit is contained in:
parent
997bc21feb
commit
cdc6d9aa65
@ -1 +1 @@
|
||||
6.0-SNAPSHOT
|
||||
6.0
|
||||
|
@ -7,6 +7,7 @@ TODO
|
||||
- why is there a beq _prog8_label_2_repeatend at the end of repeat loops? seems unused
|
||||
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
|
||||
- implement the linked_list millfork benchmark
|
||||
- use the 65c02 bit clear/set/test instructions for single-bit operations
|
||||
|
||||
- implement highres 4 color mode in gfx2
|
||||
- make a retro amiga workbench 1.3 and/or 2.0 workbench "simulator" using that new gfx mode
|
||||
|
@ -12,43 +12,48 @@ main {
|
||||
txt.lowercase()
|
||||
|
||||
repeat {
|
||||
c64.CHROUT(19) ; HOME
|
||||
txt.chrout(19) ; HOME
|
||||
txt.print("\n yyyy-mm-dd HH:MM:SS.jj\n\n")
|
||||
void cx16.clock_get_date_time()
|
||||
c64.CHROUT(' ')
|
||||
txt.chrout(' ')
|
||||
print_date()
|
||||
c64.CHROUT(' ')
|
||||
txt.chrout(' ')
|
||||
print_time()
|
||||
}
|
||||
|
||||
txt.chrout('\n')
|
||||
txt.chrout('\n')
|
||||
uword jiffies = c64.RDTIM16()
|
||||
txt.print_uw(jiffies)
|
||||
}
|
||||
}
|
||||
|
||||
sub print_date() {
|
||||
txt.print_uw(1900 + lsb(cx16.r0))
|
||||
c64.CHROUT('-')
|
||||
txt.chrout('-')
|
||||
if msb(cx16.r0) < 10
|
||||
c64.CHROUT('0')
|
||||
txt.chrout('0')
|
||||
txt.print_ub(msb(cx16.r0))
|
||||
c64.CHROUT('-')
|
||||
txt.chrout('-')
|
||||
if lsb(cx16.r1) < 10
|
||||
c64.CHROUT('0')
|
||||
txt.chrout('0')
|
||||
txt.print_ub(lsb(cx16.r1))
|
||||
}
|
||||
|
||||
sub print_time() {
|
||||
if msb(cx16.r1) < 10
|
||||
c64.CHROUT('0')
|
||||
txt.chrout('0')
|
||||
txt.print_ub(msb(cx16.r1))
|
||||
c64.CHROUT(':')
|
||||
txt.chrout(':')
|
||||
if lsb(cx16.r2) < 10
|
||||
c64.CHROUT('0')
|
||||
txt.chrout('0')
|
||||
txt.print_ub(lsb(cx16.r2))
|
||||
c64.CHROUT(':')
|
||||
txt.chrout(':')
|
||||
if msb(cx16.r2) < 10
|
||||
c64.CHROUT('0')
|
||||
txt.chrout('0')
|
||||
txt.print_ub(msb(cx16.r2))
|
||||
c64.CHROUT('.')
|
||||
txt.chrout('.')
|
||||
if lsb(cx16.r3) < 10
|
||||
c64.CHROUT('0')
|
||||
txt.chrout('0')
|
||||
txt.print_ub(lsb(cx16.r3))
|
||||
}
|
||||
}
|
||||
|
@ -1,109 +0,0 @@
|
||||
%target cx16
|
||||
%import gfx2
|
||||
%import diskio
|
||||
|
||||
bmp_module {
|
||||
|
||||
sub show_image(uword filenameptr) -> ubyte {
|
||||
ubyte load_ok = false
|
||||
ubyte[$36] header
|
||||
uword size
|
||||
uword width
|
||||
uword height
|
||||
ubyte bpp
|
||||
uword offsetx
|
||||
uword offsety
|
||||
uword palette = memory("palette", 256*4)
|
||||
uword total_read = 0
|
||||
|
||||
if diskio.f_open(8, filenameptr) {
|
||||
size = diskio.f_read(header, $36)
|
||||
if size==$36 {
|
||||
total_read = $36
|
||||
if header[0]=='b' and header[1]=='m' {
|
||||
uword bm_data_offset = mkword(header[11], header[10])
|
||||
uword header_size = mkword(header[$f], header[$e])
|
||||
width = mkword(header[$13], header[$12])
|
||||
height = mkword(header[$17], header[$16])
|
||||
bpp = header[$1c]
|
||||
uword num_colors = header[$2e]
|
||||
if num_colors == 0
|
||||
num_colors = 2**bpp
|
||||
uword skip_hdr = header_size - 40
|
||||
repeat skip_hdr
|
||||
void c64.CHRIN()
|
||||
total_read += skip_hdr
|
||||
size = diskio.f_read(palette, num_colors*4)
|
||||
if size==num_colors*4 {
|
||||
total_read += size
|
||||
repeat bm_data_offset - total_read
|
||||
void c64.CHRIN()
|
||||
gfx2.clear_screen()
|
||||
custompalette.set_bgra(palette, num_colors)
|
||||
decode_bitmap()
|
||||
load_ok = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskio.f_close()
|
||||
}
|
||||
|
||||
return load_ok
|
||||
|
||||
sub start_plot() {
|
||||
offsetx = 0
|
||||
offsety = 0
|
||||
if width < gfx2.width
|
||||
offsetx = (gfx2.width - width - 1) / 2
|
||||
if height < gfx2.height
|
||||
offsety = (gfx2.height - height - 1) / 2
|
||||
if width > gfx2.width
|
||||
width = gfx2.width
|
||||
if height > gfx2.height
|
||||
height = gfx2.height
|
||||
}
|
||||
|
||||
sub decode_bitmap() {
|
||||
start_plot()
|
||||
uword bits_width = width * bpp
|
||||
ubyte pad_bytes = (((bits_width + 31) >> 5) << 2) - ((bits_width + 7) >> 3) as ubyte
|
||||
|
||||
uword x
|
||||
uword y
|
||||
ubyte b
|
||||
for y in height-1 downto 0 {
|
||||
gfx2.position(offsetx, offsety+y)
|
||||
when bpp {
|
||||
8 -> {
|
||||
for x in 0 to width-1
|
||||
gfx2.next_pixel(c64.CHRIN())
|
||||
}
|
||||
4 -> {
|
||||
for x in 0 to width-1 step 2 {
|
||||
b = c64.CHRIN()
|
||||
gfx2.next_pixel(b>>4)
|
||||
gfx2.next_pixel(b&15)
|
||||
}
|
||||
}
|
||||
2 -> {
|
||||
for x in 0 to width-1 step 4 {
|
||||
b = c64.CHRIN()
|
||||
gfx2.next_pixel(b>>6)
|
||||
gfx2.next_pixel(b>>4 & 3)
|
||||
gfx2.next_pixel(b>>2 & 3)
|
||||
gfx2.next_pixel(b & 3)
|
||||
}
|
||||
}
|
||||
1 -> {
|
||||
for x in 0 to width-1 step 8
|
||||
gfx2.set_8_pixels_from_bits(c64.CHRIN(), 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
repeat pad_bytes
|
||||
void c64.CHRIN()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,362 +0,0 @@
|
||||
%target cx16
|
||||
%import gfx2
|
||||
%import textio
|
||||
%import diskio
|
||||
|
||||
iff_module {
|
||||
uword cmap
|
||||
uword num_colors
|
||||
uword[16] cycle_rates
|
||||
uword[16] cycle_rate_ticks
|
||||
ubyte[16] cycle_reverseflags
|
||||
ubyte[16] cycle_lows
|
||||
ubyte[16] cycle_highs
|
||||
ubyte num_cycles
|
||||
|
||||
sub show_image(uword filenameptr) -> ubyte {
|
||||
ubyte load_ok = false
|
||||
uword size
|
||||
ubyte[32] buffer
|
||||
uword camg = 0
|
||||
str chunk_id = "????"
|
||||
uword chunk_size_hi
|
||||
uword chunk_size_lo
|
||||
uword scanline_data_ptr = sys.progend()
|
||||
|
||||
uword width
|
||||
uword height
|
||||
ubyte num_planes
|
||||
ubyte compression
|
||||
ubyte have_cmap = false
|
||||
ubyte cycle_crng = false
|
||||
ubyte cycle_ccrt = false
|
||||
num_cycles = 0
|
||||
cmap = memory("palette", 256*4) ; only use 768 of these, but this allows re-use of the same block that the bmp module allocates
|
||||
|
||||
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 == "crng" {
|
||||
; DeluxePaint color cycle range
|
||||
if not cycle_ccrt {
|
||||
cycle_crng = true
|
||||
void diskio.f_read(buffer, chunk_size_lo)
|
||||
ubyte flags = buffer[5]
|
||||
if flags & 1 {
|
||||
cycle_rates[num_cycles] = mkword(buffer[2], buffer[3])
|
||||
cycle_rate_ticks[num_cycles] = 1
|
||||
cycle_lows[num_cycles] = buffer[6]
|
||||
cycle_highs[num_cycles] = buffer[7]
|
||||
cycle_reverseflags[num_cycles] = flags & 2 != 0
|
||||
num_cycles++
|
||||
}
|
||||
} else
|
||||
skip_chunk()
|
||||
}
|
||||
else if chunk_id == "ccrt" {
|
||||
; Graphicraft color cycle range
|
||||
if not cycle_crng {
|
||||
cycle_ccrt = true
|
||||
void diskio.f_read(buffer, chunk_size_lo)
|
||||
ubyte direction = buffer[1]
|
||||
if direction {
|
||||
; delay_sec = buffer[4] * 256 * 256 * 256 + buffer[5] * 256 * 256 + buffer[6] * 256 + buffer[7]
|
||||
; delay_micro = buffer[8] * 256 * 256 * 256 + buffer[9] * 256 * 256 + buffer[10] * 256 + buffer[11]
|
||||
; We're ignoring the delay_sec field for now. Not many images will have this slow of a color cycle anyway (>1 sec per cycle)
|
||||
; rate = int(16384 // (60*delay_micro/1e6))
|
||||
; float rate = (65*16384.0) / (mkword(buffer[9], buffer[10]) as float) ; fairly good approximation using float arithmetic
|
||||
cycle_rates[num_cycles] = 33280 / (mkword(buffer[9], buffer[10]) >> 5) ; reasonable approximation using only 16-bit integer arithmetic
|
||||
cycle_rate_ticks[num_cycles] = 1
|
||||
cycle_lows[num_cycles] = buffer[2]
|
||||
cycle_highs[num_cycles] = buffer[3]
|
||||
cycle_reverseflags[num_cycles] = direction == 1 ; TODO weird, the spec say that -1 = reversed but several example images that I have downloaded are the opposite
|
||||
num_cycles++
|
||||
}
|
||||
} else
|
||||
skip_chunk()
|
||||
}
|
||||
else if chunk_id == "body" {
|
||||
gfx2.clear_screen()
|
||||
if camg & $0004
|
||||
height /= 2 ; interlaced: just skip every odd scanline later
|
||||
if camg & $0080 and have_cmap
|
||||
make_ehb_palette()
|
||||
palette.set_rgb8(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()
|
||||
}
|
||||
|
||||
return load_ok
|
||||
|
||||
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++
|
||||
}
|
||||
}
|
||||
|
||||
ubyte bitplane_stride
|
||||
uword interleave_stride
|
||||
uword offsetx
|
||||
uword offsety
|
||||
|
||||
sub start_plot() {
|
||||
bitplane_stride = lsb(width>>3)
|
||||
interleave_stride = (bitplane_stride as uword) * num_planes
|
||||
offsetx = 0
|
||||
offsety = 0
|
||||
if width < gfx2.width
|
||||
offsetx = (gfx2.width - width - 1) / 2
|
||||
if height < gfx2.height
|
||||
offsety = (gfx2.height - height - 1) / 2
|
||||
if width > gfx2.width
|
||||
width = gfx2.width
|
||||
if height > gfx2.height
|
||||
height = gfx2.height
|
||||
}
|
||||
|
||||
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)
|
||||
gfx2.position(offsetx, offsety+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()
|
||||
gfx2.position(offsetx, offsety+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() {
|
||||
; ubyte[8] masks = [128,64,32,16,8,4,2,1]
|
||||
uword x
|
||||
for x in 0 to width-1 {
|
||||
; ubyte mask = masks[lsb(x) & 7]
|
||||
uword pixptr = x/8 + scanline_data_ptr
|
||||
ubyte bits = 0
|
||||
%asm {{
|
||||
bra +
|
||||
_masks .byte 128, 64, 32, 16, 8, 4, 2, 1
|
||||
+ lda pixptr
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda pixptr+1
|
||||
sta P8ZP_SCRATCH_W1+1
|
||||
lda x
|
||||
and #7
|
||||
tay
|
||||
lda _masks,y
|
||||
sta P8ZP_SCRATCH_B1 ; mask
|
||||
phx
|
||||
ldx num_planes
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
clc
|
||||
and P8ZP_SCRATCH_B1
|
||||
beq +
|
||||
sec
|
||||
+ ror bits ; shift planar bit into chunky byte
|
||||
lda P8ZP_SCRATCH_W1
|
||||
; clc
|
||||
adc bitplane_stride
|
||||
sta P8ZP_SCRATCH_W1
|
||||
bcc +
|
||||
inc P8ZP_SCRATCH_W1+1
|
||||
+ dex
|
||||
bne -
|
||||
plx
|
||||
lda #8
|
||||
sec
|
||||
sbc num_planes
|
||||
beq +
|
||||
tay
|
||||
- lsr bits
|
||||
dey
|
||||
bne -
|
||||
+
|
||||
}}
|
||||
|
||||
; the assembly above is the optimized version of this:
|
||||
; repeat num_planes {
|
||||
; clear_carry()
|
||||
; if @(pixptr) & mask
|
||||
; set_carry()
|
||||
; ror(bits) ; shift planar bit into chunky byte
|
||||
; pixptr += bitplane_stride
|
||||
; }
|
||||
; bits >>= 8-num_planes
|
||||
|
||||
gfx2.next_pixel(bits)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub cycle_colors_each_jiffy() {
|
||||
if num_cycles==0
|
||||
return
|
||||
|
||||
; TODO implement Blend Shifting see http://www.effectgames.com/demos/canvascycle/palette.js
|
||||
|
||||
ubyte changed = false
|
||||
ubyte ci
|
||||
for ci in 0 to num_cycles-1 {
|
||||
cycle_rate_ticks[ci]--
|
||||
if cycle_rate_ticks[ci]==0 {
|
||||
changed = true
|
||||
cycle_rate_ticks[ci] = 16384 / cycle_rates[ci]
|
||||
do_cycle(cycle_lows[ci], cycle_highs[ci], cycle_reverseflags[ci])
|
||||
}
|
||||
}
|
||||
|
||||
if changed
|
||||
palette.set_rgb8(cmap, num_colors) ; set the new palette
|
||||
|
||||
sub do_cycle(uword low, uword high, ubyte reversed) {
|
||||
low *= 3
|
||||
high *= 3
|
||||
uword bytecount = high-low
|
||||
uword cptr
|
||||
ubyte red
|
||||
ubyte green
|
||||
ubyte blue
|
||||
|
||||
if reversed {
|
||||
cptr = cmap + low
|
||||
red = @(cptr)
|
||||
green = @(cptr+1)
|
||||
blue = @(cptr+2)
|
||||
repeat bytecount {
|
||||
@(cptr) = @(cptr+3)
|
||||
cptr++
|
||||
}
|
||||
@(cptr) = red
|
||||
cptr++
|
||||
@(cptr) = green
|
||||
cptr++
|
||||
@(cptr) = blue
|
||||
} else {
|
||||
cptr = cmap + high
|
||||
red = @(cptr)
|
||||
cptr++
|
||||
green = @(cptr)
|
||||
cptr++
|
||||
blue = @(cptr)
|
||||
repeat bytecount {
|
||||
@(cptr) = @(cptr-3)
|
||||
cptr--
|
||||
}
|
||||
@(cptr) = blue
|
||||
cptr--
|
||||
@(cptr) = green
|
||||
cptr--
|
||||
@(cptr) = red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
%target cx16
|
||||
%import gfx2
|
||||
%import textio
|
||||
%import diskio
|
||||
%import string
|
||||
%import koala_module
|
||||
%import iff_module
|
||||
%import pcx_module
|
||||
%import bmp_module
|
||||
%zeropage basicsafe
|
||||
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
|
||||
cx16.rombank(0) ; switch to kernal rom (for faster file i/o)
|
||||
|
||||
; trick to check if we're running on sdcard or host system shared folder
|
||||
txt.print("\nimage viewer for commander x16\nformats supported: .iff, .pcx, .bmp, .koa (c64 koala)\n\n")
|
||||
if string.length(diskio.status(8)) {
|
||||
txt.print("enter image file name or just enter for all on disk: ")
|
||||
ubyte i = txt.input_chars(diskio.filename)
|
||||
gfx2.screen_mode(1) ; 320*240, 256c
|
||||
if i
|
||||
attempt_load(diskio.filename)
|
||||
else
|
||||
show_pics_sdcard()
|
||||
|
||||
; txt.print("\nnothing more to do.\n")
|
||||
}
|
||||
else
|
||||
txt.print("files are read with sequential file loading.\nin the emulator this currently only works with files on an sd-card image.\nsorry :(\n")
|
||||
|
||||
gfx2.screen_mode(255) ; back to default text mode and palette
|
||||
txt.print("that was all folks!\n")
|
||||
|
||||
cx16.rombank(4) ; switch back to basic rom
|
||||
}
|
||||
|
||||
sub show_pics_sdcard() {
|
||||
|
||||
; load and show the images on the disk with the given extensions.
|
||||
; this only works in the emulator V38 with an sd-card image with the files on it.
|
||||
|
||||
str[40] filename_ptrs
|
||||
ubyte num_files = diskio.list_files(8, 0, &filename_ptrs, len(filename_ptrs))
|
||||
if num_files {
|
||||
while num_files {
|
||||
num_files--
|
||||
attempt_load(filename_ptrs[num_files])
|
||||
}
|
||||
} else
|
||||
txt.print("no files in directory!\n")
|
||||
|
||||
}
|
||||
|
||||
sub attempt_load(uword filenameptr) {
|
||||
;txt.print(">> ")
|
||||
;txt.print(filenameptr)
|
||||
;txt.nl()
|
||||
uword extension = filenameptr + rfind(filenameptr, '.')
|
||||
if string.compare(extension, ".iff")==0 {
|
||||
;txt.print("loading ")
|
||||
;txt.print("iff\n")
|
||||
if iff_module.show_image(filenameptr) {
|
||||
if iff_module.num_cycles {
|
||||
repeat 500 {
|
||||
sys.wait(1)
|
||||
iff_module.cycle_colors_each_jiffy()
|
||||
}
|
||||
}
|
||||
else
|
||||
sys.wait(180)
|
||||
} else {
|
||||
load_error(filenameptr)
|
||||
}
|
||||
}
|
||||
else if string.compare(extension, ".pcx")==0 {
|
||||
;txt.print("loading ")
|
||||
;txt.print("pcx\n")
|
||||
if pcx_module.show_image(filenameptr) {
|
||||
sys.wait(180)
|
||||
} else {
|
||||
load_error(filenameptr)
|
||||
}
|
||||
}
|
||||
else if string.compare(extension,".koa")==0 {
|
||||
;txt.print("loading ")
|
||||
;txt.print("koala\n")
|
||||
if koala_module.show_image(filenameptr) {
|
||||
sys.wait(180)
|
||||
} else {
|
||||
load_error(filenameptr)
|
||||
}
|
||||
}
|
||||
else if string.compare(extension, ".bmp")==0 {
|
||||
;txt.print("loading ")
|
||||
;txt.print("bmp\n")
|
||||
if bmp_module.show_image(filenameptr) {
|
||||
sys.wait(180)
|
||||
} else {
|
||||
load_error(filenameptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub load_error(uword filenameptr) {
|
||||
gfx2.screen_mode(255) ; back to default text mode and palette
|
||||
txt.print(filenameptr)
|
||||
txt.print(": load error\n")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
sub extension_equals(uword stringptr, uword extensionptr) -> ubyte {
|
||||
ubyte ix = rfind(stringptr, '.')
|
||||
return ix<255 and string.compare(stringptr+ix, extensionptr)==0
|
||||
}
|
||||
|
||||
sub rfind(uword stringptr, ubyte char) -> ubyte {
|
||||
ubyte i
|
||||
for i in string.length(stringptr)-1 downto 0 {
|
||||
if @(stringptr+i)==char
|
||||
return i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
custompalette {
|
||||
|
||||
sub set_bgra(uword palletteptr, uword num_colors) {
|
||||
uword vera_palette_ptr = $fa00
|
||||
ubyte red
|
||||
ubyte greenblue
|
||||
|
||||
; 4 bytes per color entry (BGRA), adjust color depth from 8 to 4 bits per channel.
|
||||
repeat num_colors {
|
||||
red = @(palletteptr+2) >> 4
|
||||
greenblue = @(palletteptr+1) & %11110000
|
||||
greenblue |= @(palletteptr+0) >> 4 ; add Blue
|
||||
palletteptr+=4
|
||||
cx16.vpoke(1, vera_palette_ptr, greenblue)
|
||||
vera_palette_ptr++
|
||||
cx16.vpoke(1, vera_palette_ptr, red)
|
||||
vera_palette_ptr++
|
||||
}
|
||||
}
|
||||
|
||||
sub set_grayscale256() {
|
||||
; grays $000- $fff stretched out over all the 256 colors
|
||||
ubyte c = 0
|
||||
uword vera_palette_ptr = $fa00
|
||||
repeat 16 {
|
||||
repeat 16 {
|
||||
cx16.vpoke(1, vera_palette_ptr, c)
|
||||
vera_palette_ptr++
|
||||
cx16.vpoke(1, vera_palette_ptr, c)
|
||||
vera_palette_ptr++
|
||||
}
|
||||
c += $11
|
||||
}
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
%target cx16
|
||||
%import gfx2
|
||||
%import diskio
|
||||
%import palette
|
||||
|
||||
koala_module {
|
||||
const uword load_location = $6000
|
||||
|
||||
sub show_image(uword filenameptr) -> ubyte {
|
||||
ubyte load_ok=false
|
||||
if diskio.f_open(8, filenameptr) {
|
||||
uword size = diskio.f_read(load_location, 2) ; skip the first 2 bytes (load address)
|
||||
if size==2 {
|
||||
if diskio.f_read(load_location, 10001)==10001 {
|
||||
; set a better C64 color palette, the Cx16's default is too saturated
|
||||
palette.set_c64pepto()
|
||||
convert_koalapic()
|
||||
load_ok = true
|
||||
}
|
||||
}
|
||||
diskio.f_close()
|
||||
}
|
||||
|
||||
return load_ok
|
||||
}
|
||||
|
||||
sub convert_koalapic() {
|
||||
ubyte cy
|
||||
ubyte @zp cx
|
||||
uword @zp cy_times_forty = 0
|
||||
ubyte @zp d
|
||||
uword bitmap_ptr = load_location
|
||||
|
||||
; theoretically you could put the 8-pixel array in zeropage to squeeze out another tiny bit of performance
|
||||
ubyte[8] pixels
|
||||
|
||||
gfx2.clear_screen()
|
||||
uword offsety = (gfx2.height - 200) / 2
|
||||
|
||||
for cy in 0 to 24*8 step 8 {
|
||||
uword posy = cy + offsety
|
||||
for cx in 0 to 39 {
|
||||
uword posx = cx as uword * 8
|
||||
for d in 0 to 7 {
|
||||
gfx2.position(posx, posy + d)
|
||||
get_8_pixels()
|
||||
gfx2.next_pixels(pixels, 8)
|
||||
}
|
||||
}
|
||||
cy_times_forty += 40
|
||||
}
|
||||
|
||||
sub get_8_pixels() {
|
||||
ubyte bm = @(bitmap_ptr)
|
||||
ubyte @zp m = mcol(bm)
|
||||
pixels[7] = m
|
||||
pixels[6] = m
|
||||
bm >>= 2
|
||||
m = mcol(bm)
|
||||
pixels[5] = m
|
||||
pixels[4] = m
|
||||
bm >>= 2
|
||||
m = mcol(bm)
|
||||
pixels[3] = m
|
||||
pixels[2] = m
|
||||
bm >>= 2
|
||||
m = mcol(bm)
|
||||
pixels[1] = m
|
||||
pixels[0] = m
|
||||
bitmap_ptr++
|
||||
|
||||
sub mcol(ubyte b) -> ubyte {
|
||||
ubyte @zp color
|
||||
when b & 3 {
|
||||
0 -> color = @(load_location + 8000 + 1000 + 1000) & 15
|
||||
1 -> color = @(load_location + 8000 + cy_times_forty + cx) >>4
|
||||
2 -> color = @(load_location + 8000 + cy_times_forty + cx) & 15
|
||||
else -> color = @(load_location + 8000 + 1000 + cy_times_forty + cx) & 15
|
||||
}
|
||||
return color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
%target cx16
|
||||
%import gfx2
|
||||
%import textio
|
||||
%import diskio
|
||||
|
||||
pcx_module {
|
||||
|
||||
sub show_image(uword filenameptr) -> ubyte {
|
||||
ubyte load_ok = false
|
||||
|
||||
if diskio.f_open(8, filenameptr) {
|
||||
ubyte[128] header
|
||||
uword size = diskio.f_read(header, 128)
|
||||
if size==128 {
|
||||
if header[0] == $0a and header[2] == 1 {
|
||||
ubyte bits_per_pixel = header[3]
|
||||
if bits_per_pixel==1 or bits_per_pixel==4 or bits_per_pixel==8 {
|
||||
uword width = mkword(header[$09], header[$08]) - mkword(header[$05], header[$04]) + 1
|
||||
uword height = mkword(header[$0b], header[$0a]) - mkword(header[$07], header[$06]) + 1
|
||||
ubyte number_of_planes = header[$41]
|
||||
uword palette_format = mkword(header[$45], header[$44])
|
||||
uword num_colors = 2**bits_per_pixel
|
||||
if number_of_planes == 1 {
|
||||
if (width & 7) == 0 {
|
||||
gfx2.clear_screen()
|
||||
if palette_format==2
|
||||
custompalette.set_grayscale256()
|
||||
else if num_colors == 16
|
||||
palette.set_rgb8(&header + $10, 16)
|
||||
else if num_colors == 2
|
||||
palette.set_monochrome()
|
||||
when bits_per_pixel {
|
||||
8 -> load_ok = bitmap.do8bpp(width, height)
|
||||
4 -> load_ok = bitmap.do4bpp(width, height)
|
||||
1 -> load_ok = bitmap.do1bpp(width, height)
|
||||
}
|
||||
if load_ok {
|
||||
load_ok = c64.CHRIN()
|
||||
if load_ok == 12 {
|
||||
; there is 256 colors of palette data at the end
|
||||
uword palette_mem = sys.progend()
|
||||
load_ok = false
|
||||
size = diskio.f_read(palette_mem, 3*256)
|
||||
if size==3*256 {
|
||||
load_ok = true
|
||||
palette.set_rgb8(palette_mem, num_colors)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
txt.print("width not multiple of 8!\n")
|
||||
} else
|
||||
txt.print("has >256 colors!\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
diskio.f_close()
|
||||
}
|
||||
|
||||
return load_ok
|
||||
}
|
||||
}
|
||||
|
||||
bitmap {
|
||||
|
||||
uword offsetx
|
||||
uword offsety
|
||||
uword py
|
||||
uword px
|
||||
ubyte y_ok
|
||||
ubyte status
|
||||
|
||||
sub start_plot(uword width, uword height) {
|
||||
offsetx = 0
|
||||
offsety = 0
|
||||
y_ok = true
|
||||
py = 0
|
||||
px = 0
|
||||
if width < gfx2.width
|
||||
offsetx = (gfx2.width - width) / 2
|
||||
if height < gfx2.height
|
||||
offsety = (gfx2.height - height) / 2
|
||||
status = (not c64.READST()) or (c64.READST()&64==64)
|
||||
}
|
||||
|
||||
sub next_scanline() {
|
||||
px = 0
|
||||
py++
|
||||
y_ok = py < gfx2.height
|
||||
gfx2.position(offsetx, offsety+py)
|
||||
status = (not c64.READST()) or (c64.READST()&64==64)
|
||||
}
|
||||
|
||||
sub do1bpp(uword width, uword height) -> ubyte {
|
||||
start_plot(width, height)
|
||||
gfx2.position(offsetx, offsety)
|
||||
while py < height and status {
|
||||
ubyte b = c64.CHRIN()
|
||||
if b>>6==3 {
|
||||
b &= %00111111
|
||||
ubyte dat = c64.CHRIN()
|
||||
repeat b {
|
||||
if y_ok
|
||||
gfx2.set_8_pixels_from_bits(dat, 1, 0)
|
||||
px += 8
|
||||
}
|
||||
} else {
|
||||
if y_ok
|
||||
gfx2.set_8_pixels_from_bits(b, 1, 0)
|
||||
px += 8
|
||||
}
|
||||
if px==width
|
||||
next_scanline()
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
sub do4bpp(uword width, uword height) -> ubyte {
|
||||
start_plot(width, height)
|
||||
gfx2.position(offsetx, offsety)
|
||||
while py < height and status {
|
||||
ubyte b = c64.CHRIN()
|
||||
if b>>6==3 {
|
||||
b &= %00111111
|
||||
ubyte dat = c64.CHRIN()
|
||||
if y_ok
|
||||
repeat b {
|
||||
gfx2.next_pixel(dat>>4)
|
||||
gfx2.next_pixel(dat & 15)
|
||||
}
|
||||
px += b*2
|
||||
} else {
|
||||
if y_ok {
|
||||
gfx2.next_pixel(b>>4)
|
||||
gfx2.next_pixel(b & 15)
|
||||
}
|
||||
px += 2
|
||||
}
|
||||
if px==width
|
||||
next_scanline()
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
sub do8bpp(uword width, uword height) -> ubyte {
|
||||
start_plot(width, height)
|
||||
gfx2.position(offsetx, offsety)
|
||||
while py < height and status {
|
||||
ubyte b = c64.CHRIN()
|
||||
if b>>6==3 {
|
||||
b &= %00111111
|
||||
ubyte dat = c64.CHRIN()
|
||||
if y_ok
|
||||
repeat b
|
||||
gfx2.next_pixel(dat)
|
||||
px += b
|
||||
} else {
|
||||
if y_ok
|
||||
gfx2.next_pixel(b)
|
||||
px++
|
||||
}
|
||||
if px==width
|
||||
next_scanline()
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
}
|
@ -1,50 +1,10 @@
|
||||
%import textio
|
||||
%import diskio
|
||||
%import string
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
|
||||
|
||||
sub start() {
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy
|
||||
ubyte planet
|
||||
uword cash
|
||||
float flt
|
||||
ubyte fuel
|
||||
}
|
||||
|
||||
SaveData data
|
||||
|
||||
txt.print("size of struct: ")
|
||||
txt.print_ub(sizeof(SaveData))
|
||||
txt.chrout(';')
|
||||
txt.print_ub(sizeof(data))
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print("offset of galaxy: ")
|
||||
txt.print_ub(offsetof(data.galaxy))
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print("offset of planet: ")
|
||||
txt.print_ub(offsetof(data.planet))
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print("offset of cash: ")
|
||||
txt.print_ub(offsetof(data.cash))
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print("offset of flt: ")
|
||||
txt.print_ub(offsetof(data.flt))
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print("offset of fuel: ")
|
||||
txt.print_ub(offsetof(data.fuel))
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print("hello\n")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user