Cleaning up project structure
This commit is contained in:
@@ -0,0 +1,429 @@
|
||||
use sdl3;
|
||||
use sdl3::image;
|
||||
use sdl3::ttf;
|
||||
use types::c;
|
||||
use os;
|
||||
use io;
|
||||
use bufio;
|
||||
use fmt;
|
||||
use unix;
|
||||
use unix::poll;
|
||||
use strings;
|
||||
use uxn;
|
||||
|
||||
def WIDTH = 640;
|
||||
def HEIGHT = 480;
|
||||
def DEFAULT_SCALE = 1;
|
||||
def MAX_CONSOLE_INPUT = 0x1000;
|
||||
|
||||
export fn main() void = {
|
||||
sdl3::Init(sdl3::InitFlags::VIDEO | sdl3::InitFlags::EVENTS | sdl3::InitFlags::GAMEPAD)!;
|
||||
defer sdl3::Quit();
|
||||
|
||||
let scale = DEFAULT_SCALE;
|
||||
const win = sdl3::CreateWindow(
|
||||
c::nulstr("Meadow\0"),
|
||||
WIDTH*scale, HEIGHT*scale, sdl3::WindowFlags::RESIZABLE |
|
||||
sdl3::WindowFlags::MOUSE_CAPTURE |
|
||||
sdl3::WindowFlags::INPUT_FOCUS |
|
||||
sdl3::WindowFlags::MOUSE_FOCUS
|
||||
)!;
|
||||
defer sdl3::DestroyWindow(win);
|
||||
|
||||
sdl3::SetWindowMinimumSize(win,0,0)!;
|
||||
|
||||
const render = sdl3::CreateRenderer(win, null)!;
|
||||
defer sdl3::DestroyRenderer(render);
|
||||
sdl3::SetRenderDrawColor(render, 0, 0, 128, 255)!;
|
||||
sdl3::SetRenderVSync(render,1)!;
|
||||
|
||||
|
||||
const screen_w = WIDTH;
|
||||
const screen_h = HEIGHT;
|
||||
//Create blank texture for screen
|
||||
const meadow_texture = sdl3::CreateTexture(render,
|
||||
sdl3::PixelFormat::XRGB4444,
|
||||
sdl3::TextureAccess::STATIC,
|
||||
screen_w,
|
||||
screen_h)!;
|
||||
defer sdl3::DestroyTexture(meadow_texture);
|
||||
sdl3::SetTextureScaleMode(meadow_texture, sdl3::ScaleMode::NEAREST)!;
|
||||
// const pixeldata: [WIDTH * HEIGHT]u32 = [0...];
|
||||
let pixeldata: *[uxn::MAXWIDTH * uxn::MAXHEIGHT]u16 = alloc([0...])!; //TODO figure out actual size
|
||||
defer free (pixeldata);
|
||||
|
||||
let run = true;
|
||||
let ev = sdl3::Event { ... };
|
||||
if(len(os::args) < 2){
|
||||
fmt::printf("usage: %s file.rom [args..]\n")!;
|
||||
return;
|
||||
};
|
||||
let path = os::args[1];
|
||||
|
||||
//Setting up pollfds for uni::poll
|
||||
const consolefd: []unix::poll::pollfd = [unix::poll::pollfd {
|
||||
fd = os::stdin_file,
|
||||
events = unix::poll::event::POLLIN,
|
||||
revents = 0,
|
||||
} ];
|
||||
let state: *uxn::uxn = uxn::uxn_init(path)!;
|
||||
uxn::uxn_reset(state);
|
||||
let next_refresh: u64 = 0;
|
||||
const perf_freq: u64 = sdl3::GetPerformanceFrequency();
|
||||
const frame_interval = perf_freq / 60;
|
||||
const ms_interval = perf_freq / 1000;
|
||||
for (run) {
|
||||
const now: u64 = sdl3::GetPerformanceCounter();
|
||||
if(state.running){
|
||||
// fmt::printf("Next Step!\n")!;
|
||||
// uxn::uxn_step(state)!;
|
||||
yield;
|
||||
}else{
|
||||
if(state.console_vector != 0){
|
||||
// fmt::printf("Console!\n")!;
|
||||
let args = os::args[2..];
|
||||
let i: u8 = 0;
|
||||
let argcount = len(args): u8;
|
||||
for (let arg .. args){
|
||||
// fmt::println("Console input args")!;
|
||||
for(let char: u8 .. strings::toutf8(arg)){
|
||||
// fmt::printfln("Console input arg char: {:x}", char)!;
|
||||
match (uxn::console_input(char,2,state)) {
|
||||
case done =>
|
||||
yield done;
|
||||
case let val: u8 =>
|
||||
fmt::fatalf("Unhandled Opcode: {:x}", val);
|
||||
};
|
||||
};
|
||||
let ctype: u8 = if(i == (argcount - 1)){
|
||||
yield 4;
|
||||
} else {
|
||||
yield 3;
|
||||
};
|
||||
match (uxn::console_input('\n',ctype,state)) {
|
||||
case done =>
|
||||
yield done;
|
||||
case let val: u8 =>
|
||||
fmt::fatalf("Unhandled Opcode: {:x}", val);
|
||||
};
|
||||
i+=1; //TODO using i here seems inelegant
|
||||
};
|
||||
const pollr = unix::poll::poll(consolefd, unix::poll::NONBLOCK);
|
||||
if(pollr > 0){
|
||||
// fmt::println("Input!")!;
|
||||
let buf: [MAX_CONSOLE_INPUT]u8 = [0...];
|
||||
io::read(os::stdin_file, buf)!;
|
||||
for( let b .. buf ){
|
||||
// fmt::printfln("Input: {}",buf[0])!;
|
||||
match (uxn::console_input(b,1,state)) {
|
||||
case done =>
|
||||
yield done;
|
||||
case let val: u8 =>
|
||||
fmt::fatalf("Unhandled Opcode: {:x}", val);
|
||||
};
|
||||
// uxn::console_input(b,1,state);
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
if(now >= next_refresh){
|
||||
next_refresh = now + frame_interval;
|
||||
|
||||
if(state.screen_vector != 0){
|
||||
// fmt::println("Executing screen vector")!;
|
||||
match (uxn::uxn_eval(state.screen_vector, state)) {
|
||||
case done =>
|
||||
yield;
|
||||
case uxn::quit =>
|
||||
run = false;
|
||||
case let err: uxn::error =>
|
||||
fmt::fatalf("Error evaluating: {}", uxn::strerror(err));
|
||||
};
|
||||
};
|
||||
};
|
||||
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)!;
|
||||
if((dims.width != 0) && (dims.height !=0)){
|
||||
sdl3::DestroyTexture(meadow_texture);
|
||||
free(pixeldata);
|
||||
pixeldata = alloc([0...])!; //TODO figure out actual size
|
||||
|
||||
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*scale,h*scale)!;
|
||||
|
||||
meadow_texture = sdl3::CreateTexture(render,
|
||||
sdl3::PixelFormat::XRGB4444,
|
||||
sdl3::TextureAccess::STATIC,
|
||||
w,
|
||||
h)!;
|
||||
sdl3::SetTextureScaleMode(meadow_texture, sdl3::ScaleMode::NEAREST)!;
|
||||
|
||||
state.screen_update = true;
|
||||
};
|
||||
|
||||
|
||||
state.screen_size_changed = false;
|
||||
};
|
||||
|
||||
if(state.screen_update){
|
||||
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);
|
||||
// fmt::printfln("Pixel x: {} y: {} color: {:x} pcount: {:x}", x, y, colshort, pcount)!;
|
||||
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;
|
||||
};
|
||||
};
|
||||
const pitch: int = dims.width: int * 2;
|
||||
// fmt::printfln("Pitch is {}", pitch)!;
|
||||
if(pitch > 0) sdl3::UpdateTexture(meadow_texture, null, pixeldata, pitch)!;
|
||||
sdl3::RenderClear(render)!;
|
||||
sdl3::RenderTexture(render, meadow_texture, null, null)!;
|
||||
|
||||
sdl3::RenderPresent(render)!;
|
||||
state.screen_update = false;
|
||||
};
|
||||
|
||||
|
||||
//Render stuff
|
||||
for (sdl3::PollEvent(&ev)) {
|
||||
// fmt::println("Handling event")!;
|
||||
switch (ev.event_type) {
|
||||
case sdl3::EventType::QUIT =>
|
||||
run = false;
|
||||
case sdl3::EventType::WINDOW_RESIZED =>
|
||||
const dims = uxn::get_window_size(state);
|
||||
let w = ev.window.data1 / scale: i32;
|
||||
let h = ev.window.data2 / scale: i32;
|
||||
const wmod = w % scale: i32;
|
||||
const hmod = h % scale: i32;
|
||||
if((wmod !=0) || (hmod !=0)){
|
||||
w = w-wmod;
|
||||
h = h-hmod;
|
||||
sdl3::SetWindowSize(win,w,h)!;
|
||||
};
|
||||
|
||||
if((dims.width != w: u16 / scale: u16) || (dims.height != h: u16 / scale: 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*scale: i32,h*scale: i32)!;
|
||||
|
||||
meadow_texture = sdl3::CreateTexture(render,
|
||||
sdl3::PixelFormat::XRGB4444,
|
||||
sdl3::TextureAccess::STATIC,
|
||||
w,
|
||||
h)!;
|
||||
sdl3::SetTextureScaleMode(meadow_texture, sdl3::ScaleMode::NEAREST)!;
|
||||
|
||||
state.screen_update = true;
|
||||
};
|
||||
|
||||
case sdl3::EventType::MOUSE_MOTION =>
|
||||
// fmt::printfln("Mouse Event x: {} y: {}", ev.motion.x, ev.motion.y)!;
|
||||
const x = ev.motion.x / scale: f32;
|
||||
const y = ev.motion.y / scale: f32;
|
||||
uxn::set_mouse_motion(x: u16,y: u16,state);
|
||||
if(state.mouse_vector != 0 ){
|
||||
match (uxn::uxn_eval(state.mouse_vector, state)) {
|
||||
case done =>
|
||||
yield;
|
||||
case uxn::quit =>
|
||||
run = false;
|
||||
case let err: uxn::error =>
|
||||
fmt::fatalf("Error evaluating: {}", uxn::strerror(err));
|
||||
};
|
||||
};
|
||||
case sdl3::EventType::MOUSE_BUTTON_DOWN =>
|
||||
// fmt::printfln("Mouse Down: 0x{:x}", ev.button.button: u8 )!;
|
||||
const b = 1 << (ev.button.button: u8 - 1);
|
||||
uxn::set_mouse_down(b,state);
|
||||
if(state.mouse_vector != 0 ){
|
||||
match (uxn::uxn_eval(state.mouse_vector, state)) {
|
||||
case done =>
|
||||
yield;
|
||||
case uxn::quit =>
|
||||
run = false;
|
||||
case let err: uxn::error =>
|
||||
fmt::fatalf("Error evaluating: {}", uxn::strerror(err));
|
||||
};
|
||||
};
|
||||
case sdl3::EventType::MOUSE_BUTTON_UP =>
|
||||
// fmt::printfln("Mouse Up: 0x{:x}", ev.button.button: u8 )!;
|
||||
const b = 1 << (ev.button.button: u8 - 1);
|
||||
uxn::set_mouse_up(b,state);
|
||||
if(state.mouse_vector != 0 ){
|
||||
match (uxn::uxn_eval(state.mouse_vector, state)) {
|
||||
case done =>
|
||||
yield;
|
||||
case uxn::quit =>
|
||||
run = false;
|
||||
case let err: uxn::error =>
|
||||
fmt::fatalf("Error evaluating: {}", uxn::strerror(err));
|
||||
};
|
||||
};
|
||||
case sdl3::EventType::MOUSE_WHEEL =>
|
||||
fmt::printfln("Mouse Wheel!")!;
|
||||
case sdl3::EventType::KEY_DOWN =>
|
||||
const key = ev.key.key;
|
||||
const scancode = ev.key.scancode;
|
||||
const mods = ev.key.mod;
|
||||
const sym = sdl3::GetKeyFromScancode(scancode,mods,false);
|
||||
if( sym < 0xFF){
|
||||
uxn::set_key_down(sym: u8,state);
|
||||
};
|
||||
// Handle F Keys
|
||||
if(key == sdl3::K_F1){
|
||||
scale = (scale % 3) + 1;
|
||||
const dims = uxn::get_window_size(state);
|
||||
sdl3::SetWindowSize(win,dims.width: i32*scale: i32,dims.height: i32*scale: i32)!;
|
||||
}else if(key == sdl3::K_F2){
|
||||
uxn::emu_deo(0x0e,0x01,state);
|
||||
}else if(key == sdl3::K_F3){
|
||||
state.dev[0x0f] = 0xff;
|
||||
};
|
||||
// Handle keyboard controller keys
|
||||
// Ctrl -> A 0x01
|
||||
if(key == sdl3::K_LCTRL || key == sdl3::K_RCTRL){
|
||||
uxn::set_controller_down(0x01,state);
|
||||
};
|
||||
// Alt -> B 0x02
|
||||
if(key == sdl3::K_LALT || key == sdl3::K_RALT){
|
||||
uxn::set_controller_down(0x02,state);
|
||||
};
|
||||
// Shift -> Select 0x04
|
||||
if(key == sdl3::K_LSHIFT || key == sdl3::K_RSHIFT){
|
||||
uxn::set_controller_down(0x04,state);
|
||||
};
|
||||
// Home -> Start 0x08
|
||||
if(key == sdl3::K_HOME){
|
||||
uxn::set_controller_down(0x08,state);
|
||||
};
|
||||
// Up -> Up 0x10
|
||||
if(key == sdl3::K_UP){
|
||||
uxn::set_controller_down(0x10,state);
|
||||
};
|
||||
// Down -> Down 0x20
|
||||
if(key == sdl3::K_DOWN){
|
||||
uxn::set_controller_down(0x20,state);
|
||||
};
|
||||
// Left -> Left 0x40
|
||||
if(key == sdl3::K_LEFT){
|
||||
uxn::set_controller_down(0x40,state);
|
||||
};
|
||||
// Right -> Right 0x80
|
||||
if(key == sdl3::K_RIGHT){
|
||||
uxn::set_controller_down(0x80,state);
|
||||
};
|
||||
match (uxn::uxn_eval(state.controller_vector, state)) {
|
||||
case done =>
|
||||
yield;
|
||||
case uxn::quit =>
|
||||
run = false;
|
||||
case let err: uxn::error =>
|
||||
fmt::fatalf("Error evaluating: {}", uxn::strerror(err));
|
||||
};
|
||||
uxn::clear_key_down(state);
|
||||
|
||||
case sdl3::EventType::KEY_UP =>
|
||||
const key = ev.key.key;
|
||||
// Ctrl -> A 0x01
|
||||
if(key == sdl3::K_LCTRL || key == sdl3::K_RCTRL){
|
||||
uxn::set_controller_up(0x01,state);
|
||||
};
|
||||
// Alt -> B 0x02
|
||||
if(key == sdl3::K_LALT || key == sdl3::K_RALT){
|
||||
uxn::set_controller_up(0x02,state);
|
||||
};
|
||||
// Shift -> Select 0x04
|
||||
if(key == sdl3::K_LSHIFT || key == sdl3::K_RSHIFT){
|
||||
uxn::set_controller_up(0x04,state);
|
||||
};
|
||||
// Home -> Start 0x08
|
||||
if(key == sdl3::K_HOME){
|
||||
uxn::set_controller_up(0x08,state);
|
||||
};
|
||||
// Up -> Up 0x10
|
||||
if(key == sdl3::K_UP){
|
||||
uxn::set_controller_up(0x10,state);
|
||||
};
|
||||
// Down -> Down 0x20
|
||||
if(key == sdl3::K_DOWN){
|
||||
uxn::set_controller_up(0x20,state);
|
||||
};
|
||||
// Left -> Left 0x40
|
||||
if(key == sdl3::K_LEFT){
|
||||
uxn::set_controller_up(0x40,state);
|
||||
};
|
||||
// Right -> Right 0x80
|
||||
if(key == sdl3::K_RIGHT){
|
||||
uxn::set_controller_up(0x80,state);
|
||||
};
|
||||
match (uxn::uxn_eval(state.controller_vector, state)) {
|
||||
case done =>
|
||||
yield;
|
||||
case uxn::quit =>
|
||||
run = false;
|
||||
case let err: uxn::error =>
|
||||
fmt::fatalf("Error evaluating: {}", uxn::strerror(err));
|
||||
};
|
||||
|
||||
|
||||
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 )!;
|
||||
yield;
|
||||
};
|
||||
};
|
||||
|
||||
//TODO handle this in a better place
|
||||
if(state.dev[0x0f] != 0) run = false;
|
||||
// sdl3::RenderClear(render)!;
|
||||
// sdl3::RenderTexture(render, meadow_texture, null, null)!;
|
||||
|
||||
// sdl3::RenderPresent(render)!;
|
||||
// sdl3::Delay(1000 / 60);
|
||||
|
||||
|
||||
match(sdl3::get_error()){
|
||||
case void =>
|
||||
yield;
|
||||
case let err: sdl3::error =>
|
||||
fmt::printfln("SDL Error: {}", sdl3::strerror(err))!;
|
||||
};
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user