diff --git a/src/main.ha b/src/main.ha index da5c187..025a197 100644 --- a/src/main.ha +++ b/src/main.ha @@ -12,28 +12,22 @@ def WIDTH = 640; def HEIGHT = 480; export fn main() void = { - sdl3::Init(sdl3::InitFlags::VIDEO)!; + sdl3::Init(sdl3::InitFlags::VIDEO | sdl3::InitFlags::EVENTS)!; defer sdl3::Quit(); const win = sdl3::CreateWindow( c::nulstr("Meadow\0"), - WIDTH, HEIGHT, sdl3::WindowFlags::RESIZABLE)!; + WIDTH, HEIGHT, sdl3::WindowFlags::RESIZABLE | + sdl3::WindowFlags::MOUSE_CAPTURE | + sdl3::WindowFlags::INPUT_FOCUS | + sdl3::WindowFlags::MOUSE_FOCUS + )!; defer sdl3::DestroyWindow(win); const render = sdl3::CreateRenderer(win, null)!; defer sdl3::DestroyRenderer(render); sdl3::SetRenderDrawColor(render, 0, 0, 128, 255)!; sdl3::SetRenderVSync(render,1)!; - // 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 x = 0, y = 0; - // let xd = 1, yd = 1; const screen_w = WIDTH; @@ -124,6 +118,7 @@ export fn main() void = { next_refresh = now + frame_interval; if(state.screen_vector != 0){ + fmt::println("Executing screen vector")!; uxn::uxn_eval(state.screen_vector, state)!; }; }; @@ -178,34 +173,62 @@ export fn main() void = { //Render stuff for (sdl3::PollEvent(&ev)) { - if (ev.event_type == sdl3::EventType::QUIT) { - run = false; - }else if(ev.event_type == sdl3::EventType::WINDOW_RESIZED){ - let dims = uxn::get_window_size(state); - let w = ev.window.data1; - let h = ev.window.data2; - if((dims.width != w: u16) || (dims.height != h: u16)){ - // fmt::println("Dimensions not allowed!")!; - //TODO handle this maybe - uxn::set_window_size(w: u16,h: u16,state); - sdl3::DestroyTexture(meadow_texture); - free(pixeldata); - pixeldata = alloc([0...])!; //TODO figure out actual size - let old_w: int = dims.width: int; - let old_h: int = dims.height: int; + // fmt::println("Handling event")!; + switch (ev.event_type) { + case sdl3::EventType::QUIT => + run = false; + case sdl3::EventType::WINDOW_RESIZED => + let dims = uxn::get_window_size(state); + let w = ev.window.data1; + let h = ev.window.data2; + if((dims.width != w: u16) || (dims.height != h: u16)){ + // fmt::println("Dimensions not allowed!")!; + //TODO handle this maybe + uxn::set_window_size(w: u16,h: u16,state); + sdl3::DestroyTexture(meadow_texture); + free(pixeldata); + pixeldata = alloc([0...])!; //TODO figure out actual size + let old_w: int = dims.width: int; + let old_h: int = dims.height: int; - fmt::printfln("User setting window to width: {} height: {}", w, h)!; - sdl3::SetWindowSize(win,w,h)!; + fmt::printfln("User 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)!; + meadow_texture = sdl3::CreateTexture(render, + sdl3::PixelFormat::XRGB4444, + sdl3::TextureAccess::STATIC, + w, + h)!; - state.screen_update = true; - }; + state.screen_update = true; + }; + case sdl3::EventType::MOUSE_MOTION => + // fmt::printfln("Mouse Event x: {} y: {}", ev.motion.x, ev.motion.y)!; + uxn::set_mouse_motion(ev.motion.x: u16,ev.motion.y: u16,state); + uxn::uxn_eval(state.mouse_vector,state)!; + case sdl3::EventType::WINDOW_EXPOSED => + sdl3::RenderClear(render)!; + sdl3::RenderTexture(render, meadow_texture, null, null)!; + sdl3::RenderPresent(render)!; + case sdl3::EventType::WINDOW_SHOWN => + sdl3::RenderClear(render)!; + sdl3::RenderTexture(render, meadow_texture, null, null)!; + sdl3::RenderPresent(render)!; + case sdl3::EventType::WINDOW_PIXEL_SIZE_CHANGED => + sdl3::RenderClear(render)!; + sdl3::RenderTexture(render, meadow_texture, null, null)!; + sdl3::RenderPresent(render)!; + case sdl3::EventType::WINDOW_MOUSE_ENTER => + sdl3::RenderClear(render)!; + sdl3::RenderTexture(render, meadow_texture, null, null)!; + sdl3::HideCursor()!; + case sdl3::EventType::WINDOW_MOUSE_LEAVE => + sdl3::RenderClear(render)!; + sdl3::RenderTexture(render, meadow_texture, null, null)!; + sdl3::ShowCursor()!; + case => + fmt::printfln("Unhandled SDL event: 0x{:x} , {}", ev.event_type, ev.event_type )!; }; }; @@ -220,3 +243,4 @@ export fn main() void = { sdl3::get_error()!; }; }; + diff --git a/uxn-tests/sprites.tal b/uxn-tests/sprites.tal index ed88796..e90001d 100644 --- a/uxn-tests/sprites.tal +++ b/uxn-tests/sprites.tal @@ -1,23 +1,47 @@ |00 @System/vector $2 &expansion $2 &wst $1 &rst $1 &metadata $2 &r $2 &g $2 &b $2 &debug $1 &state $1 |20 @Screen/vector $2 &width $2 &height $2 &auto $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 -|100 +|0000 +@counter $2 + +|0100 @on-reset ( -> ) set-theme - #0020 .Screen/x DEO2 + ;on-screen .Screen/vector DEO2 + #0000 .counter STZ2 + ( draw-sprite ) + BRK + +@on-screen ( -> ) + clear-screen + draw-sprite + BRK + +@draw-sprite ( -> ) + #0020 .counter LDZ2 ADD2 .Screen/x DEO2 #0040 .Screen/y DEO2 - ( ;sprite-icn .Screen/addr DEO2 ) - ( #01 .Screen/sprite DEO ) - #00 .Screen/auto DEO + + #21 .Screen/auto DEO ;sprite2-icn .Screen/addr DEO2 #c1 .Screen/sprite DEO - BRK + + .counter LDZ2 INC2 .counter STZ2 + JMP2r @set-theme ( -- ) #f07f .System/r DEO2 #f0d6 .System/g DEO2 #f0b2 .System/b DEO2 JMP2r + + +@clear-screen ( -- ) + #0000 .Screen/x DEO2 + #0000 .Screen/y DEO2 + #00 .Screen/auto DEO + #80 .Screen/pixel DEO + #c0 .Screen/pixel DEO + JMP2r @sprite-icn 00 66 ff ff ff 7e 3c 18 diff --git a/uxn/uxn.ha b/uxn/uxn.ha index fe71c02..73bcd1f 100644 --- a/uxn/uxn.ha +++ b/uxn/uxn.ha @@ -10,11 +10,11 @@ use strings; // let ptr: [2] u8 = [0...]; // let stk: [2][0x100] u8 = [[0...],[0...]]; - export type uxn = struct { pc: u16, console_vector: u16, screen_vector: u16, + mouse_vector: u16, ram: [0x10000] u8, dev: [0x100] u8, ptr: [2] u8, @@ -39,6 +39,7 @@ fn initialize_uxn_mem() *uxn = { pc = reset_vector, console_vector = 0, screen_vector = 0, + mouse_vector = 0, ram = [0...], dev = [0...], ptr = [0...], @@ -99,6 +100,10 @@ fn emu_deo(port: u8, value: u8, state: *uxn) void = { draw_pixel(value,state); case 0x2f => draw_sprite(value,state); + case 0x91 => + let high = state.dev[0x90]; + let low = value; + state.mouse_vector = short_from_bytes(high,low); case => if( port == 0x22 || port == 0x23 || @@ -115,6 +120,13 @@ fn emu_deo(port: u8, value: u8, state: *uxn) void = { }; }; +export fn set_mouse_motion(x: u16, y: u16, state: *uxn) void = { + state.dev[0x92] = (x >> 8): u8; + state.dev[0x93] = (x): u8; + state.dev[0x94] = (y >> 8): u8; + state.dev[0x95] = (y): u8; +}; + 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]); @@ -192,7 +204,7 @@ 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): i8; + let count = ((auto & 0xf0) >> 4): u8; const auto_x = (auto & 0b00000001) != 0; const auto_y = (auto & 0b00000010) != 0; const auto_a = (auto & 0b00000100) != 0; @@ -201,24 +213,13 @@ fn draw_sprite(value: u8, state: *uxn) void = { const flipy: bool = (value & 0b00100000) != 0; const flipx: bool = (value & 0b00010000) != 0; - for(let i = 0; i <= count; i+=1){ + const x = short_from_bytes(state.dev[0x28],state.dev[0x29]); + const y = short_from_bytes(state.dev[0x2a],state.dev[0x2b]); + for(let i: u16 = 0; i <= count; i+=1){ const addr = short_from_bytes(state.dev[0x2c],state.dev[0x2d]); - const x = short_from_bytes(state.dev[0x28],state.dev[0x29]); - const y = short_from_bytes(state.dev[0x2a],state.dev[0x2b]); + const x = x + i * 8; copy_sprite_to_screen(bpp2,colors,x,y,addr,flipx,flipy,layer1,state); - if(auto_x) { - const new_x = x + 8; - state.dev[0x28] = (new_x >> 8): u8; - state.dev[0x29] = (new_x): u8; - - }; - if(auto_y) { - const new_y = y + 8; - state.dev[0x2a] = (new_y >> 8): u8; - state.dev[0x2b] = (new_y): u8; - - }; if(auto_a){ const new_addr = if(bpp2) { yield addr + 16; } else { yield addr + 8; }; @@ -226,12 +227,26 @@ fn draw_sprite(value: u8, state: *uxn) void = { state.dev[0x2d] = (new_addr): u8; }; }; + if(auto_x) { + const new_x = x + 8; + state.dev[0x28] = (new_x >> 8): u8; + state.dev[0x29] = (new_x): u8; + + }; + if(auto_y) { + const new_y = y + 8; + state.dev[0x2a] = (new_y >> 8): u8; + state.dev[0x2b] = (new_y): 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 = { const bytes_per_sprite = if(bpp2) {yield 16;} else {yield 8;}; + let dims = get_window_size(state); + let xoff: u16 = 0; let yoff: u16 = 0; @@ -240,8 +255,10 @@ fn copy_sprite_to_screen(bpp2: bool, colors: u8, x: u16, y: u16, addr: u16, flip const pixels = get_pixels_from_1bpp_sprite(addr,state); for(let p .. pixels){ const color = if(p == 0) { yield 0:u8;} else {yield colors: u8; }; - if(layer1) { state.screen.1[x+xoff][y+yoff] = color; } - else {state.screen.0[x+xoff][y+yoff] = color; }; + if((x < MAXWIDTH) && (y < MAXHEIGHT)){ + if(layer1) { state.screen.1[x+xoff][y+yoff] = color; } + else {state.screen.0[x+xoff][y+yoff] = color; }; + }; xoff += 1; if(xoff >= 8){ xoff = 0; @@ -252,40 +269,22 @@ fn copy_sprite_to_screen(bpp2: bool, colors: u8, x: u16, y: u16, addr: u16, flip const pixels = get_pixels_from_2bpp_sprite(addr,state); for(let p .. pixels){ const color = p; //TODO use colors bits - if(layer1) { state.screen.1[x+xoff][y+yoff] = color; } - else {state.screen.0[x+xoff][y+yoff] = color; }; + // fmt::printfln("x: 0x{:x}, xoff: 0x{:x}, y: 0x{:x}, yoff: 0x{:x}", x,xoff,y,yoff )!; + if((x < MAXWIDTH) && (y < MAXHEIGHT)){ + if(layer1) { state.screen.1[x+xoff][y+yoff] = color; } + else {state.screen.0[x+xoff][y+yoff] = color; }; + }; xoff += 1; if(xoff >= 8){ xoff = 0; yoff += 1; }; + // if(yoff >= 8){ + // break; + // }; }; }; - // fmt::printfln("Drawing Sprite to x: {} y: {}", x, y)!; - // for(let i = 0; i < bytes_per_sprite; i+=1){ - // const pixels = get_pixels_from_sprite(bpp2,addr,state); - // for(let p .. pixels){ - // const color: u8 = (if (bpp2){ - // yield p: u8; // implement real value based on colors value - // }else { - // if( p == 0 ) yield 0: u8; - // yield colors: u8; - - // } )& 0b00000011; - // // fmt::printfln("Drawing 2bpp: {} Sprite Pixel to x: {} y: {} color: {}", bpp2, x+xoff, y+yoff, p)!; - // if(layer1) { state.screen.1[x+xoff][y+yoff] = color; } - // else {state.screen.0[x+xoff][y+yoff] = color; }; - // xoff += 1; - // if(xoff >= 8){ - // xoff = 0; - // yoff += 1; - // }; - - - // }; - // }; - }; fn get_pixels_from_1bpp_sprite(addr: u16, state: *uxn) []u8 = {