From 81abb061b3de53f9c730b2f275ed34d2e13b2aad Mon Sep 17 00:00:00 2001 From: JJ Bliss Date: Sat, 25 Apr 2026 14:47:54 -0400 Subject: [PATCH] got basic screen working with pixel drawing and filling --- Makefile | 2 +- src/main.ha | 111 ++++++++++++++++++++++++++++++++-------------------- uxn/uxn.ha | 48 ++++++++++++++++++++--- 3 files changed, 113 insertions(+), 48 deletions(-) diff --git a/Makefile b/Makefile index 43c2be1..742740e 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ HARE_SOURCES != find . -name '*.ha' build: build/meadow run: build - build/meadow pixel.rom + build/meadow screentest.rom build/meadow: $(HARE_SOURCES) hare build $(LIBS) -o build/meadow src/ diff --git a/src/main.ha b/src/main.ha index e3d5341..1b98246 100644 --- a/src/main.ha +++ b/src/main.ha @@ -24,29 +24,30 @@ export fn main() void = { defer sdl3::DestroyRenderer(render); sdl3::SetRenderDrawColor(render, 0, 0, 128, 255)!; - const img = image::LoadTexture(render, c::nulstr("./assets/mascot.jpg\0"))!; - defer sdl3::DestroyTexture(img); + // const img = image::LoadTexture(render, c::nulstr("./assets/mascot.jpg\0"))!; + // defer sdl3::DestroyTexture(img); - let w = 0.0f32, h = 0.0f32; - sdl3::GetTextureSize(img, &w, &h)!; - sdl3::get_error()!; - const w = w: int, h = h: int; + // let w = 0.0f32, h = 0.0f32; + // sdl3::GetTextureSize(img, &w, &h)!; + // sdl3::get_error()!; + // const w = w: int, h = h: int; - let x = 0, y = 0; - let xd = 1, yd = 1; + // let x = 0, y = 0; + // let xd = 1, yd = 1; const screen_w = WIDTH; const screen_h = HEIGHT; //Create blank texture for screen const meadow_texture = sdl3::CreateTexture(render, - sdl3::PixelFormat::XRGB8888, + sdl3::PixelFormat::XRGB4444, sdl3::TextureAccess::STATIC, screen_w, screen_h)!; defer sdl3::DestroyTexture(meadow_texture); // const pixeldata: [WIDTH * HEIGHT]u32 = [0...]; - let pixeldata: *[uxn::MAXWIDTH * uxn::MAXHEIGHT]u32 = alloc([0...])!; //TODO figure out actual size + let pixeldata: *[uxn::MAXWIDTH * uxn::MAXHEIGHT]u16 = alloc([0...])!; //TODO figure out actual size + defer free (pixeldata); let run = true; let ev = sdl3::Event { ... }; @@ -116,11 +117,24 @@ export fn main() void = { }; if(state.screen_size_changed){ let dims = uxn::get_window_size(state); - fmt::printfln("Setting window to width: {:x} height: {:x}", dims.width, dims.height)!; + // fmt::printfln("Setting window to width: {:x} height: {:x}", dims.width, dims.height)!; if((dims.width != 0) && (dims.height !=0)){ - //TODO, check current dims + //TODO, check current dims + // + sdl3::DestroyTexture(meadow_texture); + let w: int = dims.width: int; + let h: int = dims.height: int; + + fmt::printfln("Setting window to width: {} height: {}", w, h)!; + sdl3::SetWindowSize(win,w,h)!; + + meadow_texture = sdl3::CreateTexture(render, + sdl3::PixelFormat::XRGB4444, + sdl3::TextureAccess::STATIC, + w, + h)!; - sdl3::SetWindowSize(win,dims.width: int,dims.height: int)!; + state.screen_update = true; }; @@ -129,20 +143,33 @@ export fn main() void = { if(state.screen_update){ let pcount = 0; - for(let x: u16 = 0; x < screen_w: u16; x+=1 ){ - for(let y: u16 = 0; y < screen_h: u16; y+=1 ){ - const colshort = uxn::get_color(x,y,state); + const dims = uxn::get_window_size(state); + for(let y: u16 = 0; y <= dims.height: u16; y+=1 ){ + for(let x: u16 = 0; x <= dims.width: u16; x+=1 ){ + let colshort: u16 = uxn::get_color(x,y,state); //take 16-bit color and transform to 32-bit number //XRGB -> XXRXGXBX - const r = (colshort & 0x0F00): u32 << (3*4); - const g = (colshort & 0x00F0): u32 << (2*4); - const b = (colshort & 0x000F): u32 << (1*4); - const color: u32 = r | g | b; + // const r = (colshort & 0x0F00): u32 << (3*4); + // const g = (colshort & 0x00F0): u32 << (2*4); + // const b = (colshort & 0x000F): u32 << (1*4); + // const color: u32 = r | g | b; // const data = pixeldata: *[*]u32; // - pixeldata[pcount] = color; + // if(colshort !=0x0fff){ + // fmt::printfln("Pixel x: {:x} y: {:x} color: {:x}", x, y, colshort)!; + // }; + // fmt::printfln("Pixel x: {} y: {} color: {:x} pcount: {:x}", x, y, colshort, pcount)!; + if(y == 0 && x < 64) colshort = 0; + const index: u32 = y: u32 * dims.width: u32 + x: u32; + // if(index < 10) fmt::printfln("pcount: {} index: {} x: {} y: {}", pcount, index, x, y)!; + pixeldata[index] = colshort; pcount +=1; }; + // pixeldata[pcount] = 0; + // pcount += 4096; }; + const pitch: int = dims.width: int * 2; + fmt::printfln("Pitch is {}", pitch)!; + if(pitch > 0) sdl3::UpdateTexture(meadow_texture, null, pixeldata, pitch)!; state.screen_update = false; }; @@ -156,33 +183,33 @@ export fn main() void = { sdl3::RenderClear(render)!; - sdl3::RenderTexture(render, img, null, &sdl3::FRect { - x = x: f32, - y = y: f32, - w = w: f32, - h = h: f32, - })!; - sdl3::UpdateTexture(meadow_texture, null, pixeldata: *opaque, 32)!; sdl3::RenderTexture(render, meadow_texture, null, null)!; + // sdl3::RenderTexture(render, img, null, &sdl3::FRect { + // x = x: f32, + // y = y: f32, + // w = w: f32, + // h = h: f32, + // })!; + sdl3::RenderPresent(render)!; sdl3::Delay(1000 / 60); - x += xd; - y += yd; - if (x + w >= WIDTH) { - xd = -1; - }; - if (x <= 0) { - xd = 1; - }; - if (y + h >= HEIGHT) { - yd = -1; - }; - if (y <= 0) { - yd = 1; - }; + // x += xd; + // y += yd; + // if (x + w >= WIDTH) { + // xd = -1; + // }; + // if (x <= 0) { + // xd = 1; + // }; + // if (y + h >= HEIGHT) { + // yd = -1; + // }; + // if (y <= 0) { + // yd = 1; + // }; sdl3::get_error()!; }; diff --git a/uxn/uxn.ha b/uxn/uxn.ha index ad0f4bf..ac79b2f 100644 --- a/uxn/uxn.ha +++ b/uxn/uxn.ha @@ -45,7 +45,7 @@ fn initialize_uxn_mem() *uxn = { stk = [[0...],[0...]], running = false, screen_size_changed = false, - screen_update = false, + screen_update = true, screen = ([[0...]...],[[0...]...]), palette = [0...], })!; @@ -117,6 +117,7 @@ fn regenerate_palettes(state: *uxn) void = { 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])!; }; @@ -125,11 +126,39 @@ fn draw_pixel(value: u8, state: *uxn) void = { 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]); - if((value & 0b01000000) == 0){ - state.screen.0[x][y] = color; - } else { - state.screen.1[x][y] = color; + 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)!; + if(!layer1){ + state.screen.0[x][y] = color; + } else { + state.screen.1[x][y] = color; + }; + }else{ + 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)!; + if(!layer1){ + state.screen.0[xl][yl] = color; + } else { + state.screen.1[xl][yl] = color; + }; + }; + }; }; + state.screen_update = true; }; @@ -803,6 +832,15 @@ export fn uxn_init(path: str) ( *uxn | error ) = { fmt::fatalf("Error reading: {}", io::strerror(err)); }; io::close(romfile)!; //TODO, isn't there some kind of oversized roms? + + //Initialize default colors TODO look for .theme files + state.dev[0x08] = 0xf0; + state.dev[0x09] = 0x7f; + state.dev[0x0a] = 0xf0; + state.dev[0x0b] = 0xd6; + state.dev[0x0c] = 0xf0; + state.dev[0x0d] = 0xb2; + regenerate_palettes(state); return state; }; export fn uxn_reset(state: *uxn) void = {