SDL Errors don't always crash the emulator. Fixed JMP relative address handling.
This commit is contained in:
+11
-1
@@ -285,6 +285,11 @@ export fn main() void = {
|
||||
const mods = ev.key.mod;
|
||||
const sym = sdl3::GetKeyFromScancode(scancode,mods,false);
|
||||
uxn::set_key_down(sym: u8,state);
|
||||
// Handle Debug
|
||||
if(key == sdl3::K_F2){
|
||||
fmt::println("Debug Print:")!;
|
||||
uxn::print_stack_debug(state);
|
||||
};
|
||||
//Handle keyboard controller keys
|
||||
// Ctrl -> A 0x01
|
||||
if(key == sdl3::K_LCTRL || key == sdl3::K_RCTRL){
|
||||
@@ -407,6 +412,11 @@ export fn main() void = {
|
||||
// sdl3::Delay(1000 / 60);
|
||||
|
||||
|
||||
sdl3::get_error()!;
|
||||
match(sdl3::get_error()){
|
||||
case void =>
|
||||
yield;
|
||||
case let err: sdl3::error =>
|
||||
fmt::printfln("SDL Error: {}", sdl3::strerror(err))!;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
+98
-165
@@ -421,6 +421,27 @@ fn get_instruction(byte: u8) (instruction | error) = {
|
||||
};
|
||||
};
|
||||
|
||||
export fn print_stack_debug(state: *uxn) void = {
|
||||
fmt::println("Working Stack:")!;
|
||||
print_stack(false,state);
|
||||
|
||||
fmt::println("Return Stack:")!;
|
||||
print_stack(true,state);
|
||||
};
|
||||
|
||||
fn print_stack(ret: bool, state: *uxn) void = {
|
||||
const p = switch(ret){
|
||||
case true =>
|
||||
yield 1;
|
||||
case false =>
|
||||
yield 0;
|
||||
};
|
||||
for(let i = state.ptr[p] - 8; i != state.ptr[p]; i+=1){
|
||||
fmt::printf("{:x} ",state.stk[p][i])!;
|
||||
};
|
||||
fmt::printf("\n")!;
|
||||
};
|
||||
|
||||
fn short_from_bytes(high: u8, low: u8) u16 = {
|
||||
return (high: u16) << 8 | (low: u16);
|
||||
};
|
||||
@@ -688,24 +709,24 @@ export fn uxn_step(state: *uxn) (done | error) = {
|
||||
let bot = pop_or_get(equ_inst,1,state);
|
||||
|
||||
//TODO, I think this works, but it feels unclean with the casting
|
||||
// let val: u8 = if(top: u16 == bot: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
let val: u8 = if(!equ_inst.short){
|
||||
yield if(bot: u8 == top: u8){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
let val: u8 = if(top: u16 == bot: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield if(bot: u16 == top: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
yield 0;
|
||||
};
|
||||
// let val: u8 = if(!equ_inst.short){
|
||||
// yield if(bot: u8 == top: u8){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// } else {
|
||||
// yield if(bot: u16 == top: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// };
|
||||
push_to_stack(equ_inst.ret, val, state);
|
||||
// /* NEQ */ OPC(0x09,POx(a,d) POx(b,d),PUx(b != a,0,r))
|
||||
case let neq_inst: NEQ =>
|
||||
@@ -713,24 +734,24 @@ export fn uxn_step(state: *uxn) (done | error) = {
|
||||
let bot = pop_or_get(neq_inst,1,state);
|
||||
|
||||
//TODO, I think this works, but it feels unclean with the casting
|
||||
// let val: u8 = if(top: u16 != bot: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
let val: u8 = if(!neq_inst.short){
|
||||
yield if(bot: u8 != top: u8){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
let val: u8 = if(top: u16 != bot: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield if(bot: u16 != top: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
yield 0;
|
||||
};
|
||||
// let val: u8 = if(!neq_inst.short){
|
||||
// yield if(bot: u8 != top: u8){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// } else {
|
||||
// yield if(bot: u16 != top: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// };
|
||||
push_to_stack(neq_inst.ret, val, state);
|
||||
// /* GTH */ OPC(0x0a,POx(a,d) POx(b,d),PUx(b > a,0,r))
|
||||
case let gth_inst: GTH =>
|
||||
@@ -738,24 +759,24 @@ export fn uxn_step(state: *uxn) (done | error) = {
|
||||
let bot = pop_or_get(gth_inst,1,state);
|
||||
|
||||
//TODO, I think this works, but it feels unclean with the casting
|
||||
// let val: u8 = if(bot: u16 > top: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
let val: u8 = if(!gth_inst.short){
|
||||
yield if(bot: u8 > top: u8){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
let val: u8 = if(bot: u16 > top: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield if(bot: u16 > top: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
yield 0;
|
||||
};
|
||||
// let val: u8 = if(!gth_inst.short){
|
||||
// yield if(bot: u8 > top: u8){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// } else {
|
||||
// yield if(bot: u16 > top: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// };
|
||||
push_to_stack(gth_inst.ret, val, state);
|
||||
// /* LTH */ OPC(0x0b,POx(a,d) POx(b,d),PUx(b < a,0,r))
|
||||
case let lth_inst: LTH =>
|
||||
@@ -763,31 +784,33 @@ export fn uxn_step(state: *uxn) (done | error) = {
|
||||
let bot = pop_or_get(lth_inst,1,state);
|
||||
|
||||
//TODO, I think this works, but it feels unclean with the casting
|
||||
// let val: u8 = if(bot: u16 < top: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
let val: u8 = if(!lth_inst.short){
|
||||
yield if(bot: u8 < top: u8){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
let val: u8 = if(bot: u16 < top: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield if(bot: u16 < top: u16){
|
||||
yield 1;
|
||||
} else {
|
||||
yield 0;
|
||||
};
|
||||
yield 0;
|
||||
};
|
||||
// let val: u8 = if(!lth_inst.short){
|
||||
// yield if(bot: u8 < top: u8){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// } else {
|
||||
// yield if(bot: u16 < top: u16){
|
||||
// yield 1;
|
||||
// } else {
|
||||
// yield 0;
|
||||
// };
|
||||
// };
|
||||
push_to_stack(lth_inst.ret, val, state);
|
||||
// /* JMP */ OPC(0x0c,POx(a,d),MOV)
|
||||
case let jmp_inst: JMP =>
|
||||
let addr = pop_or_get(jmp_inst,0,state);
|
||||
match(addr) {
|
||||
case let b: u8 =>
|
||||
state.pc = state.pc + b: u16; //TODO verify if pc changes are right
|
||||
let off = b: i8: i32;
|
||||
state.pc = (state.pc: i32 + off): u16; //TODO verify if pc changes are right
|
||||
|
||||
case let s: u16 =>
|
||||
state.pc = s;
|
||||
};
|
||||
@@ -868,15 +891,16 @@ export fn uxn_step(state: *uxn) (done | error) = {
|
||||
push_to_stack(dei_inst.ret,val,state);
|
||||
// /* DEO */ OPC(0x17,POx(a,0) GOT(y),DEO(a, y))
|
||||
case let deo_inst: DEO =>
|
||||
let port: u8 = pop_or_get(normal_op{short = false, keep = deo_inst.keep, ret = deo_inst.ret}, 0, state): u8;
|
||||
if(deo_inst.short){
|
||||
let low = pop_or_get(normal_op{short = false, keep = deo_inst.keep, ret = deo_inst.ret}, 1, state): u8;
|
||||
let high = pop_or_get(normal_op{short = false, keep = deo_inst.keep, ret = deo_inst.ret}, 2, state): u8;
|
||||
emu_deo(port,high,state);
|
||||
emu_deo(port+1,low,state);
|
||||
}else{
|
||||
let val = pop_or_get(deo_inst, 1, state): u8;
|
||||
emu_deo(port,val,state);
|
||||
const port: u8 = pop_or_get(normal_op{short = false, keep = deo_inst.keep, ret = deo_inst.ret}, 0, state): u8;
|
||||
const val = pop_or_peek(deo_inst,1,state);
|
||||
match(val){
|
||||
case let s: u16 =>
|
||||
const high: u8 = (s >> 8): u8;
|
||||
const low: u8 = s: u8;
|
||||
emu_deo(port,high,state);
|
||||
emu_deo(port+1,low,state);
|
||||
case let b: u8 =>
|
||||
emu_deo(port,b,state);
|
||||
};
|
||||
// /* ADD */ OPC(0x18,POx(a,d) POx(b,d),PUx(b + a, d,r))
|
||||
case let add_inst: ADD =>
|
||||
@@ -1026,94 +1050,3 @@ export fn uxn_reset(state: *uxn) void = {
|
||||
state.running = true;
|
||||
uxn_eval(reset_vector,state)!;
|
||||
};
|
||||
// export fn uxnrun() void = {
|
||||
// if(len(os::args) < 2){
|
||||
// fmt::printf("usage: %s file.rom [args..]\n")!;
|
||||
// return;
|
||||
// };
|
||||
// let path = os::args[1];
|
||||
// //Open rom file
|
||||
// let romfile = match (os::open(path,fs::flag::RDONLY)) {
|
||||
// case let file: io::file =>
|
||||
// yield file;
|
||||
// case let err: fs::error =>
|
||||
// fmt::fatalf("Error opening {}: {}", path, fs::strerror(err));
|
||||
// };
|
||||
// let state: *uxn = initialize_uxn_mem();
|
||||
// //Copy rom into ram
|
||||
// let bytesread = match (io::read(romfile,state.ram[0x100..0xff00])){
|
||||
// case let bytes: size =>
|
||||
// yield bytes;
|
||||
// case let eof: io::EOF =>
|
||||
// fmt::fatalf("Empty Rom");
|
||||
// case let err: io::error =>
|
||||
// fmt::fatalf("Error reading: {}", io::strerror(err));
|
||||
// };
|
||||
// io::close(romfile)!; //TODO, isn't there some kind of oversized roms?
|
||||
// // fread(&ram[0x100], 0xff00, 1, f), fclose(f);
|
||||
// let hasargs = len(os::args) > 2;
|
||||
// if(hasargs){
|
||||
// state.dev[0x17] = 1;
|
||||
// };
|
||||
// // dev[0x17] = argc > 2;
|
||||
|
||||
// let eval = match (uxn_eval(0x100, state)) {
|
||||
// case done =>
|
||||
// yield done;
|
||||
// case let val: u8 =>
|
||||
// fmt::fatalf("Unhandled Opcode: {:x}", val);
|
||||
// };
|
||||
// //TODO see if the above needs to not run if console vector not set
|
||||
// if(state.console_vector != 0){
|
||||
// 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 (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 (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
|
||||
// };
|
||||
// for( state.dev[0x0f] == 0; i+=1 ){
|
||||
// let buf: [1]u8 = [0];
|
||||
// let count = io::read(os::stdin, buf)!;
|
||||
// // fmt::println("Read input")!;
|
||||
// if(count != 0) {
|
||||
// match (console_input(buf[0],1,state)) {
|
||||
// case done =>
|
||||
// yield done;
|
||||
// case let val: u8 =>
|
||||
// fmt::fatalf("Unhandled Opcode: {:x}", val);
|
||||
// };
|
||||
// // fmt::println("Retuned from console_input")!;
|
||||
// };
|
||||
// };
|
||||
// // match (console_input('\n',4,state)) { //TODO should this run?
|
||||
// // case done =>
|
||||
// // yield done;
|
||||
// // case let val: u8 =>
|
||||
// // fmt::fatalf("Unhandled Opcode: {:x}", val);
|
||||
// // };
|
||||
// };
|
||||
// fmt::println("Done with uxn")!;
|
||||
|
||||
// return;
|
||||
// };
|
||||
|
||||
Reference in New Issue
Block a user