4 Commits

16 changed files with 128 additions and 35 deletions

4
Cargo.lock generated
View File

@@ -599,7 +599,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]] [[package]]
name = "curlywas" name = "curlywas"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/exoticorn/curlywas.git?rev=aac7bbd#aac7bbd8786a26da0dcbe8320b1afefaf6086464" source = "git+https://github.com/exoticorn/curlywas.git?rev=c22297e#c22297ea82977ac06373d629fb273a795322d788"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ariadne", "ariadne",
@@ -2637,7 +2637,7 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "uw8" name = "uw8"
version = "0.2.0-rc2" version = "0.2.0-rc3"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"anyhow", "anyhow",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "uw8" name = "uw8"
version = "0.2.0-rc2" version = "0.2.0-rc3"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -16,7 +16,7 @@ anyhow = "1"
minifb = { version = "0.22", default-features = false, features = ["x11"], optional = true } minifb = { version = "0.22", default-features = false, features = ["x11"], optional = true }
notify = "4" notify = "4"
pico-args = "0.4" pico-args = "0.4"
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "aac7bbd" } curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "c22297e" }
wat = "1" wat = "1"
uw8-tool = { path = "uw8-tool" } uw8-tool = { path = "uw8-tool" }
same-file = "1" same-file = "1"

2
platform/Cargo.lock generated
View File

@@ -146,7 +146,7 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]] [[package]]
name = "curlywas" name = "curlywas"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/exoticorn/curlywas.git?rev=aac7bbd#aac7bbd8786a26da0dcbe8320b1afefaf6086464" source = "git+https://github.com/exoticorn/curlywas.git?rev=c22297e#c22297ea82977ac06373d629fb273a795322d788"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ariadne", "ariadne",

View File

@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
curlywas = { git="https://github.com/exoticorn/curlywas.git", rev="aac7bbd" } curlywas = { git="https://github.com/exoticorn/curlywas.git", rev="c22297e" }
uw8-tool = { path="../uw8-tool" } uw8-tool = { path="../uw8-tool" }
anyhow = "1" anyhow = "1"
lodepng = "3.4" lodepng = "3.4"

Binary file not shown.

View File

@@ -4,6 +4,7 @@ import "env.sin" fn sin(f32) -> f32;
import "env.cos" fn cos(f32) -> f32; import "env.cos" fn cos(f32) -> f32;
import "env.pow" fn pow(f32, f32) -> f32; import "env.pow" fn pow(f32, f32) -> f32;
import "env.exp" fn exp(f32) -> f32; import "env.exp" fn exp(f32) -> f32;
import "env.logChar" fn logChar(i32);
export fn time() -> f32 { export fn time() -> f32 {
(0!64) as f32 / 1000 as f32 (0!64) as f32 / 1000 as f32
@@ -32,11 +33,9 @@ export fn random() -> i32 {
} }
export fn random64() -> i64 { export fn random64() -> i64 {
let state: i64; let lazy state = randomState ^ (randomState #>> 12i64);
randomState = (state := ( let lazy state = state ^ (state << 25i64);
state := randomState ^ (randomState #>> 12i64) randomState = state ^ (state #>> 27i64);
) ^ (state << 25i64)
) ^ (state #>> 27i64);
randomState * 0x2545f4914f6cdd1di64 randomState * 0x2545f4914f6cdd1di64
} }
@@ -62,7 +61,7 @@ export fn cls(col: i32) {
let i: i32; let i: i32;
textCursorX = 0; textCursorX = 0;
textCursorY = 0; textCursorY = 0;
graphicsText = 0; outputChannel = 0;
col = (col & 255) * 0x1010101; col = (col & 255) * 0x1010101;
loop pixels { loop pixels {
i!120 = col; i!120 = col;
@@ -307,7 +306,7 @@ global mut textCursorX = 0;
global mut textCursorY = 0; global mut textCursorY = 0;
global mut textColor = 15; global mut textColor = 15;
global mut bgColor = 0; global mut bgColor = 0;
global mut graphicsText = 0; global mut outputChannel = 0;
export fn printChar(char: i32) { export fn printChar(char: i32) {
loop chars { loop chars {
@@ -319,6 +318,18 @@ export fn printChar(char: i32) {
global mut controlCodeLength = 0; global mut controlCodeLength = 0;
fn printSingleChar(char: i32) { fn printSingleChar(char: i32) {
if char >= 4 & char <= 6 {
outputChannel = char - 4;
textCursorX = 0;
textCursorY = 0;
return;
}
if outputChannel >= 2 {
logChar(char);
return;
}
controlCodeLength?0x12d20 = char; controlCodeLength?0x12d20 = char;
controlCodeLength = controlCodeLength + 1; controlCodeLength = controlCodeLength + 1;
char = 0x12d20?0; char = 0x12d20?0;
@@ -332,13 +343,6 @@ fn printSingleChar(char: i32) {
return; return;
} }
if char == 4 | char == 5 {
graphicsText = char == 5;
textCursorX = 0;
textCursorY = 0;
return;
}
if char == 7 { if char == 7 {
80?0 = 80?0 ^ 2; 80?0 = 80?0 ^ 2;
return; return;
@@ -346,7 +350,7 @@ fn printSingleChar(char: i32) {
if char == 8 { if char == 8 {
textCursorX = textCursorX - 8; textCursorX = textCursorX - 8;
if !graphicsText & textCursorX < 0 { if !outputChannel & textCursorX < 0 {
textCursorX = 320-8; textCursorX = 320-8;
printSingleChar(11); printSingleChar(11);
} }
@@ -354,7 +358,7 @@ fn printSingleChar(char: i32) {
} }
if char == 9 { if char == 9 {
if !graphicsText & textCursorX >= 320 { if !outputChannel & textCursorX >= 320 {
printChar(0xd0a); printChar(0xd0a);
} }
textCursorX = textCursorX + 8; textCursorX = textCursorX + 8;
@@ -363,7 +367,7 @@ fn printSingleChar(char: i32) {
if char == 10 { if char == 10 {
textCursorY = textCursorY + 8; textCursorY = textCursorY + 8;
if !graphicsText & textCursorY >= 240 { if !outputChannel & textCursorY >= 240 {
textCursorY = 240 - 8; textCursorY = 240 - 8;
let i: i32; let i: i32;
loop scroll_copy { loop scroll_copy {
@@ -377,7 +381,7 @@ fn printSingleChar(char: i32) {
if char == 11 { if char == 11 {
textCursorY = textCursorY - 8; textCursorY = textCursorY - 8;
if !graphicsText & textCursorY < 0 { if !outputChannel & textCursorY < 0 {
textCursorY = 0; textCursorY = 0;
let i = 320 * (240 - 8); let i = 320 * (240 - 8);
loop scroll_copy { loop scroll_copy {
@@ -417,8 +421,8 @@ fn printSingleChar(char: i32) {
} }
if char == 31 { if char == 31 {
textCursorX = 0x12d20?1 * (8 - graphicsText * 6); textCursorX = 0x12d20?1 * (8 - outputChannel * 6);
textCursorY = 0x12d20?2 * (8 - graphicsText * 7); textCursorY = 0x12d20?2 * (8 - outputChannel * 7);
return; return;
} }
@@ -443,7 +447,7 @@ data(0x12d00) {
} }
fn drawChar(char: i32) { fn drawChar(char: i32) {
if !graphicsText & textCursorX >= 320 { if !outputChannel & textCursorX >= 320 {
printChar(0xd0a); printChar(0xd0a);
} }
@@ -451,7 +455,7 @@ fn drawChar(char: i32) {
loop rows { loop rows {
let bits = (char * 8 + y)?0x13400; let bits = (char * 8 + y)?0x13400;
let x = 0; let x = 0;
if graphicsText { if outputChannel {
loop pixels { loop pixels {
if (bits := bits << 1) & 256 { if (bits := bits << 1) & 256 {
setPixel(textCursorX + x, textCursorY + y, textColor); setPixel(textCursorX + x, textCursorY + y, textColor);
@@ -503,7 +507,7 @@ export fn setBackgroundColor(col: i32) {
} }
export fn setCursorPosition(x: i32, y: i32) { export fn setCursorPosition(x: i32, y: i32) {
let lazy scale = select(graphicsText, 1, 8); let lazy scale = select(outputChannel, 1, 8);
textCursorX = x * scale; textCursorX = x * scale;
textCursorY = y * scale; textCursorY = y * scale;
} }

View File

@@ -29,6 +29,24 @@ Examplers for older versions:
## Versions ## Versions
### v0.2.0-rc3
* [Web runtime](v0.2.0-rc3)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-windows.zip)
Changes:
* improve timing stability some more. essentially now guaranteeing that "frame = time_ms * 6 / 100" returns
consecutive frame numbers, provided the module can be run at 60 fps
* add support to redirect text output to the console for debugging using control code 6
* update curlywas:
* * add support for `else if`
* * add support for escape sequences in strings
* * add support for char literals
* * add support for binop-assignment, eg. `+=`, `^=`, `<<=` etc. (also support for the tee operator: `+:=`)
### v0.2.0-rc2 ### v0.2.0-rc2
* [Web runtime](v0.2.0-rc2) * [Web runtime](v0.2.0-rc2)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -37,6 +37,7 @@ struct UW8Instance {
end_frame: TypedFunc<(), ()>, end_frame: TypedFunc<(), ()>,
update: Option<TypedFunc<(), ()>>, update: Option<TypedFunc<(), ()>>,
start_time: Instant, start_time: Instant,
next_frame: Instant,
module: Vec<u8>, module: Vec<u8>,
watchdog: Arc<Mutex<UW8WatchDog>>, watchdog: Arc<Mutex<UW8WatchDog>>,
sound: Option<Uw8Sound>, sound: Option<Uw8Sound>,
@@ -69,8 +70,7 @@ impl MicroW8 {
resize: true, resize: true,
..Default::default() ..Default::default()
}; };
let mut window = Window::new("MicroW8", 320, 240, options)?; let window = Window::new("MicroW8", 320, 240, options)?;
window.limit_update_rate(Some(std::time::Duration::from_micros(16666)));
Ok(MicroW8 { Ok(MicroW8 {
engine, engine,
@@ -186,6 +186,7 @@ impl super::Runtime for MicroW8 {
end_frame, end_frame,
update, update,
start_time: Instant::now(), start_time: Instant::now(),
next_frame: Instant::now(),
module: module_data.into(), module: module_data.into(),
watchdog, watchdog,
sound, sound,
@@ -197,7 +198,19 @@ impl super::Runtime for MicroW8 {
fn run_frame(&mut self) -> Result<()> { fn run_frame(&mut self) -> Result<()> {
let mut result = Ok(()); let mut result = Ok(());
if let Some(mut instance) = self.instance.take() { if let Some(mut instance) = self.instance.take() {
let time = instance.start_time.elapsed().as_millis() as i32; {
if let Some(sleep) = instance.next_frame.checked_duration_since(Instant::now()) {
std::thread::sleep(sleep);
}
}
let now = Instant::now();
let time = (now - instance.start_time).as_millis() as i32;
{
let offset = ((time as u32 as i64 * 6) % 100 - 50) / 6;
instance.next_frame = now + Duration::from_millis((16 - offset) as u64);
}
{ {
let mut gamepad: u32 = 0; let mut gamepad: u32 = 0;
for key in self.window.get_keys() { for key in self.window.get_keys() {
@@ -280,6 +293,16 @@ fn add_native_functions(
for i in 10..64 { for i in 10..64 {
linker.func_wrap("env", &format!("reserved{}", i), || {})?; linker.func_wrap("env", &format!("reserved{}", i), || {})?;
} }
let log_line = std::sync::Mutex::new(String::new());
linker.func_wrap("env", "logChar", move |c: i32| {
let mut log_line = log_line.lock().unwrap();
if c == 10 {
println!("{}", log_line);
log_line.clear();
} else {
log_line.push(c as u8 as char);
}
})?;
for i in 0..16 { for i in 0..16 {
linker.define( linker.define(
"env", "env",

20
test/frame_time.cwa Normal file
View File

@@ -0,0 +1,20 @@
include "../examples/include/microw8-api.cwa"
global mut pos = 0;
global mut next = 0;
export fn upd() {
let lazy t = 32!32;
let lazy tick = t * 6 / 100;
let lazy rel = t - tick * 100 / 6;
setBackgroundColor(select(tick == next, 0, select(tick < next, 0x35, 0x55)));
setCursorPosition(pos % 13 * 3, pos / 13 % 30);
if rel < 10 {
printChar(32);
}
printInt(rel);
pos = pos + 1;
next = tick + 1;
}

7
test/log.cwa Normal file
View File

@@ -0,0 +1,7 @@
include "../examples/include/microw8-api.cwa"
export fn upd() {
printChar('\06f: ');
printInt(32!32 * 6 / 100);
printChar('\n\4');
}

View File

@@ -37,6 +37,16 @@ class APU extends AudioWorkletProcessor {
importObject.env['reserved' + i] = () => { }; importObject.env['reserved' + i] = () => { };
} }
let logLine = '';
importObject.env['logChar'] = (c) => {
if(c == 10) {
console.log(logLine);
logLine = '';
} else {
logLine += String.fromCharCode(c);
}
};
for (let i = 0; i < 16; ++i) { for (let i = 0; i < 16; ++i) {
importObject.env['g_reserved' + i] = 0; importObject.env['g_reserved' + i] = 0;
} }

View File

@@ -10,7 +10,7 @@
</head> </head>
<body> <body>
<div id="uw8"> <div id="uw8">
<a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.2.0-rc2 <a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.2.0-rc3
</div> </div>
<div id="centered"> <div id="centered">
<canvas class="screen" id="screen" width="320" height="240"> <canvas class="screen" id="screen" width="320" height="240">

View File

@@ -206,6 +206,16 @@ export default function MicroW8(screen, config = {}) {
importObject.env['reserved' + i] = () => { }; importObject.env['reserved' + i] = () => { };
} }
let logLine = '';
importObject.env['logChar'] = (c) => {
if(c == 10) {
console.log(logLine);
logLine = '';
} else {
logLine += String.fromCharCode(c);
}
};
for (let i = 0; i < 16; ++i) { for (let i = 0; i < 16; ++i) {
importObject.env['g_reserved' + i] = 0; importObject.env['g_reserved' + i] = 0;
} }
@@ -318,7 +328,7 @@ export default function MicroW8(screen, config = {}) {
if (restart) { if (restart) {
runModule(currentData); runModule(currentData);
} else { } else {
window.setTimeout(mainloop, Math.round(nextFrame - now)) window.setTimeout(mainloop, nextFrame - now)
} }
} catch (err) { } catch (err) {
config.setMessage(cartridgeSize, err.toString()); config.setMessage(cartridgeSize, err.toString());