5 Commits

17 changed files with 141 additions and 36 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-rc1" 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-rc1" 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,35 @@ 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
* [Web runtime](v0.2.0-rc2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-windows.zip)
Changes:
* fix timing issues of sound playback, especially on systems with large sound buffers
### v0.2.0-rc1 ### v0.2.0-rc1
* [Web runtime](v0.2.0-rc1) * [Web runtime](v0.2.0-rc1)

File diff suppressed because one or more lines are too long

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-rc1 <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;
} }
@@ -308,7 +318,7 @@ export default function MicroW8(screen, config = {}) {
canvasCtx.putImageData(imageData, 0, 0); canvasCtx.putImageData(imageData, 0, 0);
let timeOffset = ((time * 6) % 100 - 50) / 6; let timeOffset = ((time * 6) % 100 - 50) / 6;
thisFrame = startTime + time - timeOffset / 2; thisFrame = startTime + time - timeOffset / 8;
} else { } else {
thisFrame = Date.now(); thisFrame = Date.now();
} }
@@ -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());