diff --git a/Makefile b/Makefile index 8efebe5..e9e4781 100644 --- a/Makefile +++ b/Makefile @@ -7,16 +7,15 @@ LIBS != pkg-config --libs-only-l --libs-only-L sdl3 sdl3-image HARE_SOURCES != find . -name '*.ha' -build: build/meadow - -run: build - build/meadow monospace.rom - +build: build/meadow build/meadowcli + build/meadow: $(HARE_SOURCES) hare build $(LIBS) -o build/meadow cmd/meadow build/meadowcli: $(HARE_SOURCES) hare build -o build/meadowcli cmd/meadowcli -cli: build/meadowcli - build/meadowcli factor.rom +install: build/meadow + cp ./build/meadow ~/.local/bin/ +uninstall: + rm ~/.local/bin/meadow diff --git a/cmd/meadow/main.ha b/cmd/meadow/main.ha index abaab1a..712bcfe 100644 --- a/cmd/meadow/main.ha +++ b/cmd/meadow/main.ha @@ -54,7 +54,7 @@ export fn main() void = { let run = true; let ev = sdl3::Event { ... }; if(len(os::args) < 2){ - fmt::printf("usage: %s file.rom [args..]\n")!; + fmt::printf("usage: meadow file.rom [args..]\n")!; return; }; let path = os::args[1]; diff --git a/uxn/uxn.ha b/uxn/uxn.ha index ad5b43f..9c89748 100644 --- a/uxn/uxn.ha +++ b/uxn/uxn.ha @@ -8,12 +8,6 @@ use time; use time::date; use strings; -// let console_vector: u16 = 0; -// let ram: [0x10000] u8 = [0...]; -// let dev: [0x100] u8 = [0...]; -// let ptr: [2] u8 = [0...]; -// let stk: [2][0x100] u8 = [[0...],[0...]]; - export type uxn = struct { pc: u16, console_vector: u16, @@ -119,57 +113,55 @@ export fn set_window_size(w: u16, h: u16, state: *uxn) void = { fn emu_dei(port: u8, state: *uxn) u8 = { switch(port) { - case 0x04 => - return state.ptr[0]; - case 0x05 => - return state.ptr[1]; - case 0xc0 => - const date = time::date::localnow(); - const year = time::date::year(&date); - return ((year) >> 8): u8; - case 0xc1 => - const date = time::date::localnow(); - const year = time::date::year(&date); - return year: u8; - case 0xc2 => - const date = time::date::localnow(); - return time::date::month(&date): u8 - 1; - case 0xc3 => - const date = time::date::localnow(); - return time::date::day(&date): u8; - case 0xc4 => - const date = time::date::localnow(); - return time::date::hour(&date): u8; - case 0xc5 => - const date = time::date::localnow(); - return time::date::minute(&date): u8; - case 0xc6 => - const date = time::date::localnow(); - return time::date::second(&date): u8; - case 0xc7 => - const date = time::date::localnow(); - return (time::date::weekday(&date): u8 + 1) % 7; - case 0xc8 => - const date = time::date::localnow(); - const day = time::date::yearday(&date) - 1; - return ((day) >> 8): u8; - case 0xc9 => - const date = time::date::localnow(); - const day = time::date::yearday(&date) - 1; - return day: u8; - case 0xca => - const date = time::date::localnow(); - const zone = time::date::zone(&date); - return if(zone.dst) {yield 1;} else {yield 0;}; //TODO this isn't tested - case => - return state.dev[port]; - // fmt::printfln("Read {:x} from port {:x}", val, port)!; + case 0x04 => + return state.ptr[0]; + case 0x05 => + return state.ptr[1]; + case 0xc0 => + const date = time::date::localnow(); + const year = time::date::year(&date); + return ((year) >> 8): u8; + case 0xc1 => + const date = time::date::localnow(); + const year = time::date::year(&date); + return year: u8; + case 0xc2 => + const date = time::date::localnow(); + return time::date::month(&date): u8 - 1; + case 0xc3 => + const date = time::date::localnow(); + return time::date::day(&date): u8; + case 0xc4 => + const date = time::date::localnow(); + return time::date::hour(&date): u8; + case 0xc5 => + const date = time::date::localnow(); + return time::date::minute(&date): u8; + case 0xc6 => + const date = time::date::localnow(); + return time::date::second(&date): u8; + case 0xc7 => + const date = time::date::localnow(); + return (time::date::weekday(&date): u8 + 1) % 7; + case 0xc8 => + const date = time::date::localnow(); + const day = time::date::yearday(&date) - 1; + return ((day) >> 8): u8; + case 0xc9 => + const date = time::date::localnow(); + const day = time::date::yearday(&date) - 1; + return day: u8; + case 0xca => + const date = time::date::localnow(); + const zone = time::date::zone(&date); + return if(zone.dst) {yield 1;} else {yield 0;}; //TODO this isn't tested + case => + return state.dev[port]; }; }; export fn emu_deo(port: u8, value: u8, state: *uxn) void = { - // fmt::printfln("Writing {:x} to port {:x}", value, port)!; state.dev[port] = value; switch(port) { case 0x03 => @@ -187,7 +179,6 @@ export fn emu_deo(port: u8, value: u8, state: *uxn) void = { const high = state.dev[0x10]; const low = value; state.console_vector = short_from_bytes(high,low); - // fmt::printfln("Setting console_vector to: {:x}", console_vector)!; case 0x18 => fmt::print(value: rune)!; case 0x19 => @@ -250,36 +241,36 @@ fn deo_expansion(addr: u16, state: *uxn) void = { const op = state.ram[addr]; const length = short_from_bytes(state.ram[addr+1],state.ram[addr+2]); switch(op) { - case 0x00 => //fill - const bank = short_from_bytes(state.ram[addr+3],state.ram[addr+4]): u32; - const dstaddr = short_from_bytes(state.ram[addr+5],state.ram[addr+6]): u32; - const value = state.ram[addr+7]; - fmt::printfln("expansion fill: bank: {:x} addr: {:x} value: {:x} | length: {:x}",bank,dstaddr,value,length)!; - if(bank < numbanks) for(let i: u16 =0; i < length; i+=1){ - state.ram[bank * banksize + dstaddr + i] = value; - }; - case 0x01 => //cpyl - const srcbank = short_from_bytes(state.ram[addr+3],state.ram[addr+4]): u32; - const srcaddr = short_from_bytes(state.ram[addr+5],state.ram[addr+6]): u32; - const dstbank = short_from_bytes(state.ram[addr+7],state.ram[addr+8]): u32; - const dstaddr = short_from_bytes(state.ram[addr+9],state.ram[addr+10]): u32; - fmt::printfln("Cpyl: src: {:x} <-> {:x} dst: {:x} <-> {:x} | length: {:x}",srcbank,srcaddr,dstbank,dstaddr,length)!; - if(srcbank < numbanks && dstbank < numbanks) for(let i: u16 =0; i < length; i+=1){ - const readval = state.ram[srcbank * banksize + srcaddr + i]; - state.ram[dstbank * banksize + dstaddr + i] = readval; - }; - case 0x02 => //cpr TODO are these actually different?? Either way need to not use for loop - const srcbank = short_from_bytes(state.ram[addr+3],state.ram[addr+4]): u32; - const srcaddr = short_from_bytes(state.ram[addr+5],state.ram[addr+6]): u32; - const dstbank = short_from_bytes(state.ram[addr+7],state.ram[addr+8]): u32; - const dstaddr = short_from_bytes(state.ram[addr+9],state.ram[addr+10]): u32; - fmt::printfln("Cpyr: src: {:x} <-> {:x} dst: {:x} <-> {:x} | length: {:x}",srcbank,srcaddr,dstbank,dstaddr,length)!; - if(srcbank < numbanks && dstbank < numbanks) for(let i: u16 =1; i <= length; i+=1){ - const readval = state.ram[srcbank * banksize + srcaddr + length - i]; - state.ram[dstbank * banksize + dstaddr + length - i] = readval; - }; - case => - fmt::fatalf("Unknown expansion op: 0x{:x}",op); + case 0x00 => //fill + const bank = short_from_bytes(state.ram[addr+3],state.ram[addr+4]): u32; + const dstaddr = short_from_bytes(state.ram[addr+5],state.ram[addr+6]): u32; + const value = state.ram[addr+7]; + // fmt::printfln("expansion fill: bank: {:x} addr: {:x} value: {:x} | length: {:x}",bank,dstaddr,value,length)!; + if(bank < numbanks) for(let i: u16 =0; i < length; i+=1){ + state.ram[bank * banksize + dstaddr + i] = value; + }; + case 0x01 => //cpyl + const srcbank = short_from_bytes(state.ram[addr+3],state.ram[addr+4]): u32; + const srcaddr = short_from_bytes(state.ram[addr+5],state.ram[addr+6]): u32; + const dstbank = short_from_bytes(state.ram[addr+7],state.ram[addr+8]): u32; + const dstaddr = short_from_bytes(state.ram[addr+9],state.ram[addr+10]): u32; + // fmt::printfln("Cpyl: src: {:x} <-> {:x} dst: {:x} <-> {:x} | length: {:x}",srcbank,srcaddr,dstbank,dstaddr,length)!; + if(srcbank < numbanks && dstbank < numbanks) for(let i: u16 =0; i < length; i+=1){ + const readval = state.ram[srcbank * banksize + srcaddr + i]; + state.ram[dstbank * banksize + dstaddr + i] = readval; + }; + case 0x02 => //cpr TODO are these actually different?? Either way need to not use for loop + const srcbank = short_from_bytes(state.ram[addr+3],state.ram[addr+4]): u32; + const srcaddr = short_from_bytes(state.ram[addr+5],state.ram[addr+6]): u32; + const dstbank = short_from_bytes(state.ram[addr+7],state.ram[addr+8]): u32; + const dstaddr = short_from_bytes(state.ram[addr+9],state.ram[addr+10]): u32; + // fmt::printfln("Cpyr: src: {:x} <-> {:x} dst: {:x} <-> {:x} | length: {:x}",srcbank,srcaddr,dstbank,dstaddr,length)!; + if(srcbank < numbanks && dstbank < numbanks) for(let i: u16 =1; i <= length; i+=1){ + const readval = state.ram[srcbank * banksize + srcaddr + length - i]; + state.ram[dstbank * banksize + dstaddr + length - i] = readval; + }; + case => + fmt::fatalf("Unknown expansion op: 0x{:x}",op); }; }; @@ -342,92 +333,91 @@ fn get_instruction(byte: u8) (instruction | error) = { let s: bool = (byte & (0b00100000) != 0 ); let opcode: u8 = byte & (0b00011111); switch(opcode) { + case 0x00 => + switch(byte){ case 0x00 => - switch(byte){ - case 0x00 => - return void: BRK; - case 0x20 => - return void: JCI; - case 0x40 => - return void: JMI; - case 0x60 => - return void: JSI; - case 0x80 => // LIT - return LIT {short=false, ret=false}; - case 0xa0 => // LIT2 - return LIT {short=true, ret=false}; - case 0xc0 => // LITr - return LIT {short=false, ret=true}; - case 0xe0 => // LIT2r - return LIT {short=true, ret=true}; - case => - return byte: unhandled; - }; - case 0x01 => - return INC {short = s, keep = k, ret = r}; - case 0x02 => - return POP {short = s, keep = k, ret = r}; - case 0x03 => - return NIP {short = s, keep = k, ret = r}; - case 0x04 => - return SWP {short = s, keep = k, ret = r}; - case 0x05 => - return ROT {short = s, keep = k, ret = r}; - case 0x06 => - return DUP {short = s, keep = k, ret = r}; - case 0x07 => - return OVR {short = s, keep = k, ret = r}; - case 0x08 => - return EQU {short = s, keep = k, ret = r}; - case 0x09 => - return NEQ {short = s, keep = k, ret = r}; - case 0x0a => - return GTH {short = s, keep = k, ret = r}; - case 0x0b => - return LTH {short = s, keep = k, ret = r}; - case 0x0c => - return JMP {short = s, keep = k, ret = r}; - case 0x0d => - return JCN {short = s, keep = k, ret = r}; - case 0x0e => - return JSR {short = s, keep = k, ret = r}; - case 0x0f => - return STH {short = s, keep = k, ret = r}; - - case 0x10 => - return LDZ {short = s, keep = k, ret = r}; - case 0x11 => - return STZ {short = s, keep = k, ret = r}; - case 0x12 => - return LDR {short = s, keep = k, ret = r}; - case 0x13 => - return STR {short = s, keep = k, ret = r}; - case 0x14 => - return LDA {short = s, keep = k, ret = r}; - case 0x15 => - return STA {short = s, keep = k, ret = r}; - case 0x16 => - return DEI {short = s, keep = k, ret = r}; - case 0x17 => - return DEO {short = s, keep = k, ret = r}; - case 0x18 => - return ADD {short = s, keep = k, ret = r}; - case 0x19 => - return SUB {short = s, keep = k, ret = r}; - case 0x1a => - return MUL {short = s, keep = k, ret = r}; - case 0x1b => - return DIV {short = s, keep = k, ret = r}; - case 0x1c => - return AND {short = s, keep = k, ret = r}; - case 0x1d => - return ORA {short = s, keep = k, ret = r}; - case 0x1e => - return EOR {short = s, keep = k, ret = r}; - case 0x1f => - return SFT {short = s, keep = k, ret = r}; + return void: BRK; + case 0x20 => + return void: JCI; + case 0x40 => + return void: JMI; + case 0x60 => + return void: JSI; + case 0x80 => // LIT + return LIT {short=false, ret=false}; + case 0xa0 => // LIT2 + return LIT {short=true, ret=false}; + case 0xc0 => // LITr + return LIT {short=false, ret=true}; + case 0xe0 => // LIT2r + return LIT {short=true, ret=true}; case => return byte: unhandled; + }; + case 0x01 => + return INC {short = s, keep = k, ret = r}; + case 0x02 => + return POP {short = s, keep = k, ret = r}; + case 0x03 => + return NIP {short = s, keep = k, ret = r}; + case 0x04 => + return SWP {short = s, keep = k, ret = r}; + case 0x05 => + return ROT {short = s, keep = k, ret = r}; + case 0x06 => + return DUP {short = s, keep = k, ret = r}; + case 0x07 => + return OVR {short = s, keep = k, ret = r}; + case 0x08 => + return EQU {short = s, keep = k, ret = r}; + case 0x09 => + return NEQ {short = s, keep = k, ret = r}; + case 0x0a => + return GTH {short = s, keep = k, ret = r}; + case 0x0b => + return LTH {short = s, keep = k, ret = r}; + case 0x0c => + return JMP {short = s, keep = k, ret = r}; + case 0x0d => + return JCN {short = s, keep = k, ret = r}; + case 0x0e => + return JSR {short = s, keep = k, ret = r}; + case 0x0f => + return STH {short = s, keep = k, ret = r}; + case 0x10 => + return LDZ {short = s, keep = k, ret = r}; + case 0x11 => + return STZ {short = s, keep = k, ret = r}; + case 0x12 => + return LDR {short = s, keep = k, ret = r}; + case 0x13 => + return STR {short = s, keep = k, ret = r}; + case 0x14 => + return LDA {short = s, keep = k, ret = r}; + case 0x15 => + return STA {short = s, keep = k, ret = r}; + case 0x16 => + return DEI {short = s, keep = k, ret = r}; + case 0x17 => + return DEO {short = s, keep = k, ret = r}; + case 0x18 => + return ADD {short = s, keep = k, ret = r}; + case 0x19 => + return SUB {short = s, keep = k, ret = r}; + case 0x1a => + return MUL {short = s, keep = k, ret = r}; + case 0x1b => + return DIV {short = s, keep = k, ret = r}; + case 0x1c => + return AND {short = s, keep = k, ret = r}; + case 0x1d => + return ORA {short = s, keep = k, ret = r}; + case 0x1e => + return EOR {short = s, keep = k, ret = r}; + case 0x1f => + return SFT {short = s, keep = k, ret = r}; + case => + return byte: unhandled; }; }; @@ -442,10 +432,10 @@ export fn print_stack_debug(state: *uxn) void = { fn print_stack(ret: bool, state: *uxn) void = { const p = switch(ret){ - case true => - yield 1; - case false => - yield 0; + 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])!; @@ -459,82 +449,80 @@ fn short_from_bytes(high: u8, low: u8) u16 = { fn read_from_addr(short: bool, addr: u16, state: *uxn) (u8 | u16) = { switch(short){ - case true => - const high = state.ram[addr]; - const low = state.ram[addr+1]; - return short_from_bytes(high,low); + case true => + const high = state.ram[addr]; + const low = state.ram[addr+1]; + return short_from_bytes(high,low); - case false => - return state.ram[addr]; + case false => + return state.ram[addr]; }; }; fn write_to_addr(value: (u8 | u16), addr: u16, state: *uxn) void = { match(value){ - case let s: u16 => - let high = (s >> 8 ): u8; - let low = s: u8; - state.ram[addr] = high; - state.ram[addr+1] = low; + case let s: u16 => + let high = (s >> 8 ): u8; + let low = s: u8; + state.ram[addr] = high; + state.ram[addr+1] = low; - case let b: u8 => - state.ram[addr] = b; + case let b: u8 => + state.ram[addr] = b; }; }; fn read_from_zaddr(short: bool, zaddr: u8, state: *uxn) (u8 | u16) = { switch(short){ - case true => - const high = state.ram[zaddr: u16]; - const low = state.ram[(zaddr+1): u16]; - return short_from_bytes(high,low); - - case false => - return state.ram[zaddr: u16]; + case true => + const high = state.ram[zaddr: u16]; + const low = state.ram[(zaddr+1): u16]; + return short_from_bytes(high,low); + case false => + return state.ram[zaddr: u16]; }; }; fn write_to_zaddr(value: (u8 | u16), zaddr: u8, state: *uxn) void = { match(value){ - case let s: u16 => - let high = (s >> 8 ): u8; - let low = s: u8; - state.ram[zaddr: u16] = high; - state.ram[(zaddr+1): u16] = low; - - case let b: u8 => - state.ram[zaddr: u16] = b; + case let s: u16 => + let high = (s >> 8 ): u8; + let low = s: u8; + state.ram[zaddr: u16] = high; + state.ram[(zaddr+1): u16] = low; + case let b: u8 => + state.ram[zaddr: u16] = b; }; }; fn push_to_stack(ret: bool, val: (u8 | u16), state: *uxn) void = { let stack = switch(ret){ - case true => - yield 1; - case false => - yield 0; + case true => + yield 1; + case false => + yield 0; }; match(val) { - case let bval: u8 => - state.stk[stack][state.ptr[stack]] = bval; - state.ptr[stack] = state.ptr[stack] + 1; + case let bval: u8 => + state.stk[stack][state.ptr[stack]] = bval; + state.ptr[stack] = state.ptr[stack] + 1; - case let sval: u16 => - let low: u8 = (sval & 0xFF): u8; - let high: u8 = (sval >> 8): u8; - state.stk[stack][state.ptr[stack]] = high; - state.ptr[stack] = state.ptr[stack] + 1; - state.stk[stack][state.ptr[stack]] = low; - state.ptr[stack] = state.ptr[stack] + 1; + case let sval: u16 => + let low: u8 = (sval & 0xFF): u8; + let high: u8 = (sval >> 8): u8; + state.stk[stack][state.ptr[stack]] = high; + state.ptr[stack] = state.ptr[stack] + 1; + state.stk[stack][state.ptr[stack]] = low; + state.ptr[stack] = state.ptr[stack] + 1; }; }; // Get value from stack, offset 0 is top of stack. offset depends on short or byte fn get_stack_val(ret: bool, short: bool, off: u8, state: *uxn) (u8 | u16) = { let stack = switch(ret){ - case true => - yield 1; - case false => - yield 0; + case true => + yield 1; + case false => + yield 0; }; if(!short){ @@ -550,10 +538,10 @@ fn get_stack_val(ret: bool, short: bool, off: u8, state: *uxn) (u8 | u16) = { //peek offset is always byte offset fn peek(ret: bool, short: bool, off: u8, state: *uxn) (u8 | u16 ) = { let stack = switch(ret){ - case true => - yield 1; - case false => - yield 0; + case true => + yield 1; + case false => + yield 0; }; if(!short){ @@ -569,10 +557,10 @@ fn peek(ret: bool, short: bool, off: u8, state: *uxn) (u8 | u16 ) = { fn increment_stack(ret: bool, short: bool, state: *uxn) void = { let stack = switch(ret){ - case true => - yield 1; - case false => - yield 0; + case true => + yield 1; + case false => + yield 0; }; if(short){ state.ptr[stack] = state.ptr[stack] + 2; @@ -582,10 +570,10 @@ fn increment_stack(ret: bool, short: bool, state: *uxn) void = { }; fn decrement_stack(ret: bool, short: bool, state: *uxn) void = { let stack = switch(ret){ - case true => - yield 1; - case false => - yield 0; + case true => + yield 1; + case false => + yield 0; }; if(short){ state.ptr[stack] = state.ptr[stack] - 2; @@ -602,19 +590,19 @@ fn pop_from_stack(keep: bool, ret: bool, short: bool, state: *uxn) (u8 | u16) = fn pop_or_get(inst: normal_op, off: u8, state: *uxn) (u8 | u16) = { return switch(inst.keep) { - case false => - yield pop_from_stack(false,inst.ret,inst.short,state); - case true => - yield get_stack_val(inst.ret,inst.short, off,state); + case false => + yield pop_from_stack(false,inst.ret,inst.short,state); + case true => + yield get_stack_val(inst.ret,inst.short, off,state); }; }; //Offset is always byte aligned in peek fn pop_or_peek(inst: normal_op, off: u8, state: *uxn) (u8 | u16) = { return switch(inst.keep) { - case false => - yield pop_from_stack(false,inst.ret,inst.short,state); - case true => - yield peek(inst.ret,inst.short, off,state); + case false => + yield pop_from_stack(false,inst.ret,inst.short,state); + case true => + yield peek(inst.ret,inst.short, off,state); }; }; export fn uxn_eval(new_pc: u16, state: *uxn) (done | quit | error ) = { @@ -635,217 +623,133 @@ export fn uxn_step(state: *uxn) (done | error) = { state.pc += 1; //TODO verify all pc changes match(inst) { - // /* BRK */ case 0x00: return 1; - case BRK => - // fmt::println("Break!")!; - state.running = false; - return done; - // /* JCI */ case 0x20: if(DEC(0)) { IMM state.pc += a; } else pc += 2; break; - case JCI => - const val: u8 = pop_from_stack(false, false, false, state): u8; - if(val != 0) { - state.pc += 2 + short_from_bytes(state.ram[state.pc],state.ram[state.pc+1]); //TODO, is this signed? - }else{ - state.pc += 2; - }; - // /* JMI */ case 0x40: IMM pc += a; break; - case JMI => - state.pc = state.pc + 2 + short_from_bytes(state.ram[state.pc],state.ram[state.pc+1]); //TODO is this signed? - // /* JSI */ case 0x60: IMM PUx(pc, 1, 1) pc += a; break; - case JSI => - push_to_stack(true, state.pc + 2, state); - state.pc = state.pc + 2 + short_from_bytes(state.ram[state.pc],state.ram[state.pc+1]); //TODO is this signed? - - // /* LIT */ case 0x80: INC(0) = ram[pc++]; break; - case let lit_inst: LIT => - push_to_stack(lit_inst.ret, state.ram[state.pc], state); + case BRK => + // fmt::println("Break!")!; + state.running = false; + return done; + case JCI => + const val: u8 = pop_from_stack(false, false, false, state): u8; + if(val != 0) { + state.pc += 2 + short_from_bytes(state.ram[state.pc],state.ram[state.pc+1]); //TODO, is this signed? + }else{ + state.pc += 2; + }; + case JMI => + state.pc = state.pc + 2 + short_from_bytes(state.ram[state.pc],state.ram[state.pc+1]); //TODO is this signed? + case JSI => + push_to_stack(true, state.pc + 2, state); + state.pc = state.pc + 2 + short_from_bytes(state.ram[state.pc],state.ram[state.pc+1]); //TODO is this signed? + case let lit_inst: LIT => + push_to_stack(lit_inst.ret, state.ram[state.pc], state); + state.pc = state.pc + 1; + if(lit_inst.short) { + push_to_stack(lit_inst.ret, state.ram[state.pc],state); state.pc = state.pc + 1; - if(lit_inst.short) { - push_to_stack(lit_inst.ret, state.ram[state.pc],state); - state.pc = state.pc + 1; - }; - // /* INC */ OPC(0x01,POx(a,d),PUx(a + 1,d,r)) - case let inc_inst: INC => - const val = match(pop_from_stack(inc_inst.keep,inc_inst.ret,inc_inst.short,state)) { - //TODO this whole match statement seems unnecessary - case let byte: u8 => - yield byte + 1; - case let short: u16 => - yield short + 1; - }; - - push_to_stack(inc_inst.ret,val,state); - // /* POP */ OPC(0x02,ptr[r] -= 1 + d;,{}) - case let pop_inst: POP => - if(!pop_inst.keep){ - pop_from_stack(false,pop_inst.ret,pop_inst.short,state); - }; - // /* NIP */ OPC(0x03,GOT(x) ptr[r] -= 1 + d;,PUT(x,r)) - case let nip_inst: NIP => - const top = pop_or_get(nip_inst,0,state); - const bot = pop_or_get(nip_inst,1,state); - push_to_stack(nip_inst.ret, top, state); - // /* SWP */ OPC(0x04,GOT(x) GOT(y),PUT(x,r) PUT(y,r)) - case let swp_inst: SWP => - const top = pop_or_get(swp_inst,0,state); - const bot = pop_or_get(swp_inst,1,state); - - push_to_stack(swp_inst.ret, top, state); - push_to_stack(swp_inst.ret, bot, state); - // /* ROT */ OPC(0x05,GOT(x) GOT(y) GOT(z),PUT(y,r) PUT(x,r) PUT(z,r)) - case let rot_inst: ROT => - const top = pop_or_get(rot_inst,0,state); - const mid = pop_or_get(rot_inst,1,state); - const bot = pop_or_get(rot_inst,2,state); - - push_to_stack(rot_inst.ret, mid, state); - push_to_stack(rot_inst.ret, top, state); - push_to_stack(rot_inst.ret, bot, state); - // /* DUP */ OPC(0x06,GOT(x),PUT(x,r) PUT(x,r)) - case let dup_inst: DUP => - const val = pop_from_stack(dup_inst.keep, dup_inst.ret, dup_inst.short, state); - push_to_stack(dup_inst.ret, val, state); - push_to_stack(dup_inst.ret, val, state); - // /* OVR */ OPC(0x07,GOT(x) GOT(y),PUT(y,r) PUT(x,r) PUT(y,r)) - case let ovr_inst: OVR => - const top = pop_or_get(ovr_inst,0,state); - const bot = pop_or_get(ovr_inst,1,state); - - push_to_stack(ovr_inst.ret, bot, state); - push_to_stack(ovr_inst.ret, top, state); - push_to_stack(ovr_inst.ret, bot, state); - // /* EQU */ OPC(0x08,POx(a,d) POx(b,d),PUx(b == a,0,r)) - case let equ_inst: EQU => - const top = pop_or_get(equ_inst,0,state); - const 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; - // }; - // } 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 => - const top = pop_or_get(neq_inst,0,state); - const 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; - // }; - // } 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 => - const top = pop_or_get(gth_inst,0,state); - const 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; - // }; - // } 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 => - const top = pop_or_get(lth_inst,0,state); - const 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; - // }; - // } 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 => - const addr = pop_or_get(jmp_inst,0,state); - match(addr) { - case let b: u8 => - 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; - }; + }; + case let inc_inst: INC => + const val = match(pop_from_stack(inc_inst.keep,inc_inst.ret,inc_inst.short,state)) { + //TODO this whole match statement seems unnecessary + case let byte: u8 => + yield byte + 1; + case let short: u16 => + yield short + 1; + }; - // /* JCN */ OPC(0x0d,POx(a,d) POx(b,0),if(b) MOV) - case let jcn_inst: JCN => - const addr = pop_or_get(jcn_inst,0,state); - const cond: u8 = pop_or_peek(normal_op {keep = jcn_inst.keep, - ret = jcn_inst.ret, - short = false}, - if(jcn_inst.short){ yield 2;} else { yield 1; }, state ): u8; - if( cond != 0) { - match(addr) { - case let b: u8 => - 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; - }; - }; - // /* JSR */ OPC(0x0e,POx(a,d),PUx(pc,1,!r) MOV) - case let jsr_inst: JSR => - let addr = pop_or_get(jsr_inst,0,state); - push_to_stack(true, state.pc, state); + push_to_stack(inc_inst.ret,val,state); + case let pop_inst: POP => + if(!pop_inst.keep){ + pop_from_stack(false,pop_inst.ret,pop_inst.short,state); + }; + case let nip_inst: NIP => + const top = pop_or_get(nip_inst,0,state); + const bot = pop_or_get(nip_inst,1,state); + push_to_stack(nip_inst.ret, top, state); + case let swp_inst: SWP => + const top = pop_or_get(swp_inst,0,state); + const bot = pop_or_get(swp_inst,1,state); + + push_to_stack(swp_inst.ret, top, state); + push_to_stack(swp_inst.ret, bot, state); + case let rot_inst: ROT => + const top = pop_or_get(rot_inst,0,state); + const mid = pop_or_get(rot_inst,1,state); + const bot = pop_or_get(rot_inst,2,state); + + push_to_stack(rot_inst.ret, mid, state); + push_to_stack(rot_inst.ret, top, state); + push_to_stack(rot_inst.ret, bot, state); + case let dup_inst: DUP => + const val = pop_from_stack(dup_inst.keep, dup_inst.ret, dup_inst.short, state); + push_to_stack(dup_inst.ret, val, state); + push_to_stack(dup_inst.ret, val, state); + case let ovr_inst: OVR => + const top = pop_or_get(ovr_inst,0,state); + const bot = pop_or_get(ovr_inst,1,state); + + push_to_stack(ovr_inst.ret, bot, state); + push_to_stack(ovr_inst.ret, top, state); + push_to_stack(ovr_inst.ret, bot, state); + case let equ_inst: EQU => + const top = pop_or_get(equ_inst,0,state); + const 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; + }; + push_to_stack(equ_inst.ret, val, state); + case let neq_inst: NEQ => + const top = pop_or_get(neq_inst,0,state); + const 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; + }; + push_to_stack(neq_inst.ret, val, state); + case let gth_inst: GTH => + const top = pop_or_get(gth_inst,0,state); + const 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; + }; + push_to_stack(gth_inst.ret, val, state); + case let lth_inst: LTH => + const top = pop_or_get(lth_inst,0,state); + const 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; + }; + push_to_stack(lth_inst.ret, val, state); + case let jmp_inst: JMP => + const addr = pop_or_get(jmp_inst,0,state); + match(addr) { + case let b: u8 => + 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; + }; + case let jcn_inst: JCN => + const addr = pop_or_get(jcn_inst,0,state); + const cond: u8 = pop_or_peek(normal_op {keep = jcn_inst.keep, + ret = jcn_inst.ret, + short = false}, + if(jcn_inst.short){ yield 2;} else { yield 1; }, state ): u8; + if( cond != 0) { match(addr) { case let b: u8 => let off = b: i8: i32; @@ -853,160 +757,152 @@ export fn uxn_step(state: *uxn) (done | error) = { case let s: u16 => state.pc = s; }; - - // /* STH */ OPC(0x0f,GOT(x),PUT(x,!r)) - case let sth_inst: STH => - const val = pop_from_stack(sth_inst.keep,sth_inst.ret,sth_inst.short,state); - push_to_stack(!sth_inst.ret, val, state); - // /* LDZ */ OPC(0x10,POx(a,0),PEK(a, x, 0xff)) - case let ldz_inst: LDZ => - let addr: u8 = pop_from_stack(ldz_inst.keep, ldz_inst.ret, false, state): u8; - let val = read_from_zaddr(ldz_inst.short,addr,state); - push_to_stack(ldz_inst.ret, val, state); - // /* STZ */ OPC(0x11,POx(a,0) GOT(y),POK(a, y, 0xff)) - case let stz_inst: STZ => - let addr: u8 = pop_or_peek(normal_op{short = false, keep = stz_inst.keep, ret = stz_inst.ret}, 0, state): u8; - let val = pop_or_peek(stz_inst,1,state); - write_to_zaddr(val,addr,state); - // /* LDR */ OPC(0x12,POx(a,0),PEK(pc + (Sint8)a, x, 0xffff)) - case let ldr_inst: LDR => - let reladdr = (pop_from_stack(ldr_inst.keep, ldr_inst.ret, false, state): u16): i8; - let addr: u16 = (state.pc: u32: i32 + reladdr): u16; - let val = read_from_addr(ldr_inst.short,addr,state); - push_to_stack(ldr_inst.ret, val, state); - // /* STR */ OPC(0x13,POx(a,0) GOT(y),POK(pc + (Sint8)a, y, 0xffff)) - case let str_inst: STR => - let reladdr = (pop_or_peek(normal_op{short = false, keep = str_inst.keep, ret = str_inst.ret}, 0, state): u16 & 0x00FF): u8: i8; - let addr: u16 = (state.pc: u32: i32 + reladdr): u16; - let val = pop_or_peek(str_inst,1,state); - write_to_addr(val,addr,state); - // /* LDA */ OPC(0x14,POx(a,1),PEK(a, x, 0xffff)) - case let lda_inst: LDA => - let addr: u16 = pop_from_stack(lda_inst.keep, lda_inst.ret, true, state): u16; - let val = read_from_addr(lda_inst.short,addr,state); - push_to_stack(lda_inst.ret, val, state); - // /* STA */ OPC(0x15,POx(a,1) GOT(y),POK(a, y, 0xffff)) - case let sta_inst: STA => - let addr: u16 = pop_or_peek(normal_op{short = true, keep = sta_inst.keep, ret = sta_inst.ret}, 0, state): u16 ; - let val = pop_or_peek(sta_inst,2,state); - write_to_addr(val,addr,state); - // /* DEI */ OPC(0x16,POx(a,0),DEI(a, x)) - case let dei_inst: DEI => - // fmt::println("DEI Instruction")!; - let port: u8 = pop_from_stack(dei_inst.keep, dei_inst.ret, false, state): u8; - let val = if(dei_inst.short){ - yield short_from_bytes(emu_dei(port,state),emu_dei(port+1,state)); - }else{ - yield emu_dei(port,state); - }; - push_to_stack(dei_inst.ret,val,state); - // /* DEO */ OPC(0x17,POx(a,0) GOT(y),DEO(a, y)) - case let deo_inst: DEO => - 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 => - let top = pop_or_get(add_inst,0,state); - let bot = pop_or_get(add_inst,1,state); - let res = if(!add_inst.short){ - yield (top: u8 + bot: u8); - } else { - // fmt::printfln("ADD2 0x{:x} + 0x{:x} = 0x{:x}",bot,top,top: u16 + bot: u16)!; - yield (top: u16 + bot: u16); - }; - push_to_stack(add_inst.ret, res, state); - // /* SUB */ OPC(0x19,POx(a,d) POx(b,d),PUx(b - a, d,r)) - case let sub_inst: SUB => - let top = pop_or_get(sub_inst,0,state); - let bot = pop_or_get(sub_inst,1,state); - let res = if(!sub_inst.short){ - yield (bot: u8 - top: u8); - } else { - yield (bot: u16 - top: u16); - }; - push_to_stack(sub_inst.ret, res, state); - // /* MUL */ OPC(0x1a,POx(a,d) POx(b,d),PUx(b * a, d,r)) - case let mul_inst: MUL => - let top = pop_or_get(mul_inst,0,state); - let bot = pop_or_get(mul_inst,1,state); - let res = if(!mul_inst.short){ - yield (bot: u8 * top: u8); - } else { - yield (bot: u16 * top: u16); - }; - push_to_stack(mul_inst.ret, res, state); - // /* DIV */ OPC(0x1b,POx(a,d) POx(b,d),PUx(a ? b / a : 0, d,r)) - case let div_inst: DIV => - let top = pop_or_get(div_inst,0,state); - let bot = pop_or_get(div_inst,1,state); - - let res = if(!div_inst.short){ - assert(bot is u8); - assert(top is u8); - if(top: u8 == 0) yield top; - yield (bot: u8 / top: u8): u8; - } else { - assert(bot is u16); - assert(top is u16); - if(top: u16 == 0) yield top; - yield (bot: u16 / top: u16): u16; - };//TODO handle rounding and edge cases with division - push_to_stack(div_inst.ret, res, state); - // /* AND */ OPC(0x1c,POx(a,d) POx(b,d),PUx(b & a, d,r)) - case let and_inst: AND => - let top = pop_or_get(and_inst,0,state); - let bot = pop_or_get(and_inst,1,state); - let res = if(!and_inst.short){ - yield (bot: u8 & top: u8); - } else { - yield (bot: u16 & top: u16); - }; - push_to_stack(and_inst.ret, res, state); - // /* ORA */ OPC(0x1d,POx(a,d) POx(b,d),PUx(b | a, d,r)) - case let ora_inst: ORA => - let top = pop_or_get(ora_inst,0,state); - let bot = pop_or_get(ora_inst,1,state); - let res = if(!ora_inst.short){ - yield (bot: u8 | top: u8); - } else { - yield (bot: u16 | top: u16); - }; - push_to_stack(ora_inst.ret, res, state); - // /* EOR */ OPC(0x1e,POx(a,d) POx(b,d),PUx(b ^ a, d,r)) - case let eor_inst: EOR => - let top = pop_or_get(eor_inst,0,state); - let bot = pop_or_get(eor_inst,1,state); - let res = if(!eor_inst.short){ - yield (bot: u8 ^ top: u8); - } else { - yield (bot: u16 ^ top: u16); - }; - push_to_stack(eor_inst.ret, res, state); - // /* SFT */ OPC(0x1f,POx(a,0) POx(b,d),PUx(b >> (a & 0xf) << (a >> 4), d,r)) - case let sft_inst: SFT => - let shifts: u8 = pop_or_peek(normal_op{short = false, keep = sft_inst.keep, ret = sft_inst.ret}, 0, state): u8; - let rightshifts = shifts & 0b00001111; - let leftshifts = ((shifts & 0b11110000) >> 4) & 0b00001111; - let val = pop_or_peek(sft_inst,1,state); - let res = match(val) { - case let s: u16 => - yield (s >> rightshifts ) << leftshifts; - case let b: u8 => - yield (b >> rightshifts ) << leftshifts; - }; - push_to_stack(sft_inst.ret, res, state); + }; + case let jsr_inst: JSR => + let addr = pop_or_get(jsr_inst,0,state); + push_to_stack(true, state.pc, state); + match(addr) { + case let b: u8 => + 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; + }; + + case let sth_inst: STH => + const val = pop_from_stack(sth_inst.keep,sth_inst.ret,sth_inst.short,state); + push_to_stack(!sth_inst.ret, val, state); + case let ldz_inst: LDZ => + let addr: u8 = pop_from_stack(ldz_inst.keep, ldz_inst.ret, false, state): u8; + let val = read_from_zaddr(ldz_inst.short,addr,state); + push_to_stack(ldz_inst.ret, val, state); + case let stz_inst: STZ => + let addr: u8 = pop_or_peek(normal_op{short = false, keep = stz_inst.keep, ret = stz_inst.ret}, 0, state): u8; + let val = pop_or_peek(stz_inst,1,state); + write_to_zaddr(val,addr,state); + case let ldr_inst: LDR => + let reladdr = (pop_from_stack(ldr_inst.keep, ldr_inst.ret, false, state): u16): i8; + let addr: u16 = (state.pc: u32: i32 + reladdr): u16; + let val = read_from_addr(ldr_inst.short,addr,state); + push_to_stack(ldr_inst.ret, val, state); + case let str_inst: STR => + let reladdr = (pop_or_peek(normal_op{short = false, keep = str_inst.keep, ret = str_inst.ret}, 0, state): u16 & 0x00FF): u8: i8; + let addr: u16 = (state.pc: u32: i32 + reladdr): u16; + let val = pop_or_peek(str_inst,1,state); + write_to_addr(val,addr,state); + case let lda_inst: LDA => + let addr: u16 = pop_from_stack(lda_inst.keep, lda_inst.ret, true, state): u16; + let val = read_from_addr(lda_inst.short,addr,state); + push_to_stack(lda_inst.ret, val, state); + case let sta_inst: STA => + let addr: u16 = pop_or_peek(normal_op{short = true, keep = sta_inst.keep, ret = sta_inst.ret}, 0, state): u16 ; + let val = pop_or_peek(sta_inst,2,state); + write_to_addr(val,addr,state); + case let dei_inst: DEI => + let port: u8 = pop_from_stack(dei_inst.keep, dei_inst.ret, false, state): u8; + let val = if(dei_inst.short){ + yield short_from_bytes(emu_dei(port,state),emu_dei(port+1,state)); + }else{ + yield emu_dei(port,state); + }; + push_to_stack(dei_inst.ret,val,state); + case let deo_inst: DEO => + 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); + }; + case let add_inst: ADD => + let top = pop_or_get(add_inst,0,state); + let bot = pop_or_get(add_inst,1,state); + let res = if(!add_inst.short){ + yield (top: u8 + bot: u8); + } else { + yield (top: u16 + bot: u16); + }; + push_to_stack(add_inst.ret, res, state); + case let sub_inst: SUB => + let top = pop_or_get(sub_inst,0,state); + let bot = pop_or_get(sub_inst,1,state); + let res = if(!sub_inst.short){ + yield (bot: u8 - top: u8); + } else { + yield (bot: u16 - top: u16); + }; + push_to_stack(sub_inst.ret, res, state); + case let mul_inst: MUL => + let top = pop_or_get(mul_inst,0,state); + let bot = pop_or_get(mul_inst,1,state); + let res = if(!mul_inst.short){ + yield (bot: u8 * top: u8); + } else { + yield (bot: u16 * top: u16); + }; + push_to_stack(mul_inst.ret, res, state); + case let div_inst: DIV => + let top = pop_or_get(div_inst,0,state); + let bot = pop_or_get(div_inst,1,state); + + let res = if(!div_inst.short){ + assert(bot is u8); + assert(top is u8); + if(top: u8 == 0) yield top; + yield (bot: u8 / top: u8): u8; + } else { + assert(bot is u16); + assert(top is u16); + if(top: u16 == 0) yield top; + yield (bot: u16 / top: u16): u16; + };//TODO handle rounding and edge cases with division + push_to_stack(div_inst.ret, res, state); + case let and_inst: AND => + let top = pop_or_get(and_inst,0,state); + let bot = pop_or_get(and_inst,1,state); + let res = if(!and_inst.short){ + yield (bot: u8 & top: u8); + } else { + yield (bot: u16 & top: u16); + }; + push_to_stack(and_inst.ret, res, state); + case let ora_inst: ORA => + let top = pop_or_get(ora_inst,0,state); + let bot = pop_or_get(ora_inst,1,state); + let res = if(!ora_inst.short){ + yield (bot: u8 | top: u8); + } else { + yield (bot: u16 | top: u16); + }; + push_to_stack(ora_inst.ret, res, state); + case let eor_inst: EOR => + let top = pop_or_get(eor_inst,0,state); + let bot = pop_or_get(eor_inst,1,state); + let res = if(!eor_inst.short){ + yield (bot: u8 ^ top: u8); + } else { + yield (bot: u16 ^ top: u16); + }; + push_to_stack(eor_inst.ret, res, state); + case let sft_inst: SFT => + let shifts: u8 = pop_or_peek(normal_op{short = false, keep = sft_inst.keep, ret = sft_inst.ret}, 0, state): u8; + let rightshifts = shifts & 0b00001111; + let leftshifts = ((shifts & 0b11110000) >> 4) & 0b00001111; + let val = pop_or_peek(sft_inst,1,state); + let res = match(val) { + case let s: u16 => + yield (s >> rightshifts ) << leftshifts; + case let b: u8 => + yield (b >> rightshifts ) << leftshifts; + }; + push_to_stack(sft_inst.ret, res, state); - case => - return readval: unhandled; + case => + return readval: unhandled; }; return done; }; @@ -1024,21 +920,21 @@ export fn strerror(err: error) str = { export fn uxn_init(path: str) ( *uxn | error ) = { 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)); - }; + 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..(BANKS_CAP - 0x100)])){ - 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)); - }; + 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? //Initialize default size