Files
meadow/uxn/screen.ha
T
2026-05-05 18:25:38 -04:00

235 lines
7.4 KiB
Hare

fn draw_pixel(value: u8, state: *uxn) void = {
//TODO handle fill
const color = value & 0b00000011;
const x = short_from_bytes(state.dev[0x28],state.dev[0x29]);
const y = short_from_bytes(state.dev[0x2a],state.dev[0x2b]);
const fill: bool = (value & 0b10000000) != 0;
const layer1: bool = (value & 0b01000000) != 0;
const flipy: bool = (value & 0b00100000) != 0;
const flipx: bool = (value & 0b00010000) != 0;
if(!fill){
// fmt::printfln("Pixel at x: {:x} y: {:x} color: {:x}", x, y, color)!;
const auto = state.dev[0x26];
let count = ((auto & 0xf0) >> 4): i8;
const auto_x = (auto & 0b00000001) != 0;
const auto_y = (auto & 0b00000010) != 0;
const auto_a = (auto & 0b00000100) != 0;
set_pixel(layer1,x,y,color,state);
if(auto_x) {
const new_x = x + 1;
state.dev[0x28] = (new_x >> 8): u8;
state.dev[0x29] = (new_x): u8;
};
if(auto_y) {
const new_y = y + 1;
state.dev[0x2a] = (new_y >> 8): u8;
state.dev[0x2b] = (new_y): u8;
};
}else{
//TODO see if auto still happens with fill
// fmt::println("Doing Fill")!;
const dims = get_window_size(state);
const startx: u16 = if(flipx) {yield 0; }else{ yield x; };
const starty: u16 = if(flipy) {yield 0; }else{ yield y; };
const endx: u16 = if(flipx) {yield x; }else{ yield dims.width; };
const endy: u16 = if(flipy) {yield y; }else{ yield dims.height; };
// fmt::printfln("Fill startx: {:x} endx: {:x} starty: {:x} endy: {:x}", startx, endx, starty, endy)!;
for(let xl = startx; xl < endx; xl+=1){
for(let yl = starty; yl < endy; yl+=1){
// fmt::printfln("Filling at x: {:x} y: {:x} color: {:x}", xl, yl, color)!;
set_pixel(layer1,xl,yl,color,state);
};
};
};
state.screen_update = true;
};
fn set_pixel(layer1: bool,x: u16, y: u16,color: u8, state: *uxn) void = {
if(x > MAXWIDTH || y > MAXHEIGHT){
return;
};
if(!layer1){
state.screen.0[x][y] = color;
} else {
state.screen.1[x][y] = color;
};
};
fn regenerate_palettes(state: *uxn) void = {
const r = short_from_bytes(state.dev[0x08],state.dev[0x09]);
const g = short_from_bytes(state.dev[0x0a],state.dev[0x0b]);
const b = short_from_bytes(state.dev[0x0c],state.dev[0x0d]);
state.palette[0] = ((r & 0xf000) >> 4) | ((g & 0xf000) >> 8) | ((b & 0xf000) >> 12);
state.palette[1] = ((r & 0x0f00) >> 0) | ((g & 0x0f00) >> 4) | ((b & 0x0f00) >> 8);
state.palette[2] = ((r & 0x00f0) << 4) | ((g & 0x00f0) >> 0) | ((b & 0x00f0) >> 4);
state.palette[3] = ((r & 0x000f) << 8) | ((g & 0x000f) << 4) | ((b & 0x000f) >> 0);
// fmt::printfln("Palette Color0: {:x} Color1: {:x} Color2: {:x} Color3: {:x}", state.palette[0], state.palette[1],state.palette[2],state.palette[3])!;
};
fn draw_sprite(value: u8, state: *uxn) void = {
//TODO handle fill
const colors = value & 0b00001111;
const auto = state.dev[0x26];
let count = ((auto & 0xf0) >> 4): u8;
const auto_x = (auto & 0b00000001) != 0;
const auto_y = (auto & 0b00000010) != 0;
const auto_a = (auto & 0b00000100) != 0;
const bpp2: bool = (value & 0b10000000) != 0;
const layer1: bool = (value & 0b01000000) != 0;
const flipy: bool = (value & 0b00100000) != 0;
const flipx: bool = (value & 0b00010000) != 0;
const x = short_from_bytes(state.dev[0x28],state.dev[0x29]);
const y = short_from_bytes(state.dev[0x2a],state.dev[0x2b]);
if(count == 0){
const addr = short_from_bytes(state.dev[0x2c],state.dev[0x2d]);
// const x = if(flipx) { yield x - i * 8; } else { yield x + i * 8; };
copy_sprite_to_screen(bpp2,colors,x,y,addr,flipx,flipy,layer1,state);
if(auto_a){
const new_addr = if(bpp2) { yield addr + 16; } else { yield addr + 8; };
state.dev[0x2c] = (new_addr >> 8): u8;
state.dev[0x2d] = (new_addr): u8;
};
if(auto_x) {
const new_x = if(flipx) { yield x - 8; } else { yield x + 8; };
state.dev[0x28] = (new_x >> 8): u8;
state.dev[0x29] = (new_x): u8;
};
if(auto_y) {
const new_y = if(flipy) { yield y - 8; } else { yield y + 8; };
state.dev[0x2a] = (new_y >> 8): u8;
state.dev[0x2b] = (new_y): u8;
};
}else {
// fmt::printfln("Multi-Sprite! Auto-x: {} Auto-y: {} Flip-x: {} Flip-y: {}",auto_x,auto_y,flipx,flipy)!;
for(let i: u16 = 0; i <= count; i+=1){
const addr = short_from_bytes(state.dev[0x2c],state.dev[0x2d]);
let x = x;
let y = y;
if(auto_y) {
x = if(flipx) { yield x - i * 8; } else { yield x + i * 8; };
}else if(auto_x) {
y = if(flipy) { yield y - i * 8; } else { yield y + i * 8; };
};
copy_sprite_to_screen(bpp2,colors,x,y,addr,flipx,flipy,layer1,state);
if(auto_a){
const new_addr = if(bpp2) { yield addr + 16; } else { yield addr + 8; };
state.dev[0x2c] = (new_addr >> 8): u8;
state.dev[0x2d] = (new_addr): u8;
};
};
if(auto_y) {
const new_y = if(flipy){ yield y - 8; } else { yield y + 8; };
state.dev[0x2a] = (new_y >> 8): u8;
state.dev[0x2b] = (new_y): u8;
};
if(auto_x) {
const new_x = x + 8;
state.dev[0x28] = (new_x >> 8): u8;
state.dev[0x29] = (new_x): u8;
};
};
state.screen_update = true;
};
fn copy_sprite_to_screen(bpp2: bool, colors: u8, x: u16, y: u16, addr: u16, flipx: bool, flipy: bool, layer1: bool, state: *uxn) void = {
let dims = get_window_size(state);
let xoff: u16 = if(flipx){ yield 7; } else { yield 0; };
let yoff: u16 = if(flipy){ yield 7; } else { yield 0; };
const drawZero = ((colors%5 != 0));
const pixels: []u8 = if(bpp2) { yield get_pixels_from_2bpp_sprite(addr,state); }
else {yield get_pixels_from_1bpp_sprite(addr,state);};
for(let p .. pixels){
let color = colormodes[p][colors];
if(drawZero || p > 0){
set_pixel(layer1,x+xoff,y+yoff,color,state);
};
if(flipx){
xoff -= 1;
}else {
xoff += 1;
};
if(xoff >= 8){
xoff = if(flipx){ yield 7; } else { yield 0; };
if(flipy){
yoff -=1;
}else{
yoff += 1;
};
};
};
};
fn get_pixels_from_1bpp_sprite(addr: u16, state: *uxn) []u8 = {
let pixels: [64]u8 = [0...];
for(let i = 0; i < 8; i+=1){
let data: u8 = state.ram[addr + i: u16];
pixels[i*8 +0] = (data & 0b10000000) >> 7;
pixels[i*8 +1] = (data & 0b01000000) >> 6;
pixels[i*8 +2] = (data & 0b00100000) >> 5;
pixels[i*8 +3] = (data & 0b00010000) >> 4;
pixels[i*8 +4] = (data & 0b00001000) >> 3;
pixels[i*8 +5] = (data & 0b00000100) >> 2;
pixels[i*8 +6] = (data & 0b00000010) >> 1;
pixels[i*8 +7] = (data & 0b00000001) >> 0;
};
return pixels;
};
fn get_pixels_from_2bpp_sprite(addr: u16, state: *uxn) []u8 = {
let pixels: [64]u8 = [0...];
for(let i = 0; i < 8; i+=1){
const data1: u8 = state.ram[addr + i: u16];
const data2: u8 = state.ram[addr + i:u16 + 8];
pixels[i*8 +0] = ((data2 & 0b10000000) >> 6) | ((data1 & 0b10000000) >> 7);
pixels[i*8 +1] = ((data2 & 0b01000000) >> 5) | ((data1 & 0b01000000) >> 6);
pixels[i*8 +2] = ((data2 & 0b00100000) >> 4) | ((data1 & 0b00100000) >> 5);
pixels[i*8 +3] = ((data2 & 0b00010000) >> 3) | ((data1 & 0b00010000) >> 4);
pixels[i*8 +4] = ((data2 & 0b00001000) >> 2) | ((data1 & 0b00001000) >> 3);
pixels[i*8 +5] = ((data2 & 0b00000100) >> 1) | ((data1 & 0b00000100) >> 2);
pixels[i*8 +6] = ((data2 & 0b00000010) >> 0) | ((data1 & 0b00000010) >> 1);
pixels[i*8 +7] = ((data2 & 0b00000001) << 1) | ((data1 & 0b00000001) >> 0);
};
return pixels;
};
export fn get_color(x: u16, y: u16, state: *uxn) u16 = {
// check layer 1
let color = state.screen.1[x][y] & 0b00000011;
if(color == 0){
color = state.screen.0[x][y] & 0b00000011;
};
return state.palette[color];
};