mirror of
https://github.com/irmen/prog8.git
synced 2025-08-14 22:27:48 +00:00
moved cx16 imageviewer into its own git repo. Version 6.0.
This commit is contained in:
@@ -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
|
- 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))
|
- 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
|
- 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
|
- 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
|
- 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()
|
txt.lowercase()
|
||||||
|
|
||||||
repeat {
|
repeat {
|
||||||
c64.CHROUT(19) ; HOME
|
txt.chrout(19) ; HOME
|
||||||
txt.print("\n yyyy-mm-dd HH:MM:SS.jj\n\n")
|
txt.print("\n yyyy-mm-dd HH:MM:SS.jj\n\n")
|
||||||
void cx16.clock_get_date_time()
|
void cx16.clock_get_date_time()
|
||||||
c64.CHROUT(' ')
|
txt.chrout(' ')
|
||||||
print_date()
|
print_date()
|
||||||
c64.CHROUT(' ')
|
txt.chrout(' ')
|
||||||
print_time()
|
print_time()
|
||||||
}
|
|
||||||
|
txt.chrout('\n')
|
||||||
|
txt.chrout('\n')
|
||||||
|
uword jiffies = c64.RDTIM16()
|
||||||
|
txt.print_uw(jiffies)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print_date() {
|
sub print_date() {
|
||||||
txt.print_uw(1900 + lsb(cx16.r0))
|
txt.print_uw(1900 + lsb(cx16.r0))
|
||||||
c64.CHROUT('-')
|
txt.chrout('-')
|
||||||
if msb(cx16.r0) < 10
|
if msb(cx16.r0) < 10
|
||||||
c64.CHROUT('0')
|
txt.chrout('0')
|
||||||
txt.print_ub(msb(cx16.r0))
|
txt.print_ub(msb(cx16.r0))
|
||||||
c64.CHROUT('-')
|
txt.chrout('-')
|
||||||
if lsb(cx16.r1) < 10
|
if lsb(cx16.r1) < 10
|
||||||
c64.CHROUT('0')
|
txt.chrout('0')
|
||||||
txt.print_ub(lsb(cx16.r1))
|
txt.print_ub(lsb(cx16.r1))
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print_time() {
|
sub print_time() {
|
||||||
if msb(cx16.r1) < 10
|
if msb(cx16.r1) < 10
|
||||||
c64.CHROUT('0')
|
txt.chrout('0')
|
||||||
txt.print_ub(msb(cx16.r1))
|
txt.print_ub(msb(cx16.r1))
|
||||||
c64.CHROUT(':')
|
txt.chrout(':')
|
||||||
if lsb(cx16.r2) < 10
|
if lsb(cx16.r2) < 10
|
||||||
c64.CHROUT('0')
|
txt.chrout('0')
|
||||||
txt.print_ub(lsb(cx16.r2))
|
txt.print_ub(lsb(cx16.r2))
|
||||||
c64.CHROUT(':')
|
txt.chrout(':')
|
||||||
if msb(cx16.r2) < 10
|
if msb(cx16.r2) < 10
|
||||||
c64.CHROUT('0')
|
txt.chrout('0')
|
||||||
txt.print_ub(msb(cx16.r2))
|
txt.print_ub(msb(cx16.r2))
|
||||||
c64.CHROUT('.')
|
txt.chrout('.')
|
||||||
if lsb(cx16.r3) < 10
|
if lsb(cx16.r3) < 10
|
||||||
c64.CHROUT('0')
|
txt.chrout('0')
|
||||||
txt.print_ub(lsb(cx16.r3))
|
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 textio
|
||||||
%import diskio
|
|
||||||
%import string
|
|
||||||
%import floats
|
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option no_sysinit
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
txt.print("hello\n")
|
||||||
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')
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user