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 = if(flipx){ yield x - 1; }else{ yield x + 1; }; // const new_x = x + 1; state.dev[0x28] = (new_x >> 8): u8; state.dev[0x29] = (new_x): u8; }; if(auto_y) { const new_y = if(flipy){ yield y - 1; }else{ yield y + 1; }; // 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])!; state.screen_update = true; }; 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 = if(flipx) { yield x - 8; } else { yield x + 8; }; // 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]; };