Skip to content

Commit aeef59f

Browse files
authored
Merge pull request #4 from Neotron-Compute/keyboard-fixups
Update to latest common-BIOS
2 parents 65cb0f4 + 38f759c commit aeef59f

File tree

2 files changed

+101
-60
lines changed

2 files changed

+101
-60
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ license-file = "LICENSE"
99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

1111
[dependencies]
12-
neotron-common-bios = "0.7"
12+
neotron-common-bios = "0.8"
1313
libloading = "0.7"
1414
pix-engine = "0.5.4"
1515
env_logger = "0.9"

src/main.rs

Lines changed: 100 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,48 @@ enum AppEvent {
6262
/// The VRAM we share in a very hazardous way with the OS.
6363
///
6464
/// Big enough for 640x480 @ 256 colour.
65-
static mut FRAMEBUFFER: [u8; 307200] = [0u8; 307200];
65+
// static mut FRAMEBUFFER: [u8; 307200] = [0u8; 307200];
66+
static FRAMEBUFFER: Framebuffer<{ 640 * 480 }> = Framebuffer::new();
67+
68+
struct Framebuffer<const N: usize> {
69+
contents: std::cell::UnsafeCell<[u8; N]>,
70+
}
71+
72+
impl<const N: usize> Framebuffer<N> {
73+
const fn new() -> Framebuffer<N> {
74+
Framebuffer {
75+
contents: std::cell::UnsafeCell::new([0u8; N]),
76+
}
77+
}
78+
79+
fn write_at(&self, offset: usize, value: u8) {
80+
if offset > std::mem::size_of_val(&self.contents) {
81+
panic!("Out of bounds framebuffer write");
82+
}
83+
unsafe {
84+
let array_ptr = self.contents.get() as *mut u8;
85+
let byte_ptr = array_ptr.add(offset);
86+
byte_ptr.write_volatile(value);
87+
}
88+
}
89+
90+
fn get_at(&self, offset: usize) -> u8 {
91+
if offset > std::mem::size_of_val(&self.contents) {
92+
panic!("Out of bounds framebuffer read");
93+
}
94+
unsafe {
95+
let array_ptr = self.contents.get() as *const u8;
96+
let byte_ptr = array_ptr.add(offset);
97+
byte_ptr.read_volatile()
98+
}
99+
}
100+
101+
fn get_pointer(&self) -> *mut u8 {
102+
self.contents.get() as *mut u8
103+
}
104+
}
105+
106+
unsafe impl<const N: usize> Sync for Framebuffer<N> {}
66107

67108
/// Scale the display to make it readable on a modern monitor
68109
const SCALE_FACTOR: f32 = 2.0;
@@ -655,7 +696,7 @@ static EV_QUEUE: std::sync::Mutex<Option<std::sync::mpsc::Receiver<AppEvent>>> =
655696

656697
/// The entry point to our program.
657698
///
658-
/// We set up a game window using ggez. The event loop pumps in this thread.
699+
/// We set up a game window using PixEngine. The event loop pumps in this thread.
659700
///
660701
/// We then load the OS from the `so` file given, and jump to it in a new thread.
661702
fn main() {
@@ -666,13 +707,16 @@ fn main() {
666707

667708
*BOOT_TIME.lock().unwrap() = Some(std::time::Instant::now());
668709

710+
let white_on_black = common::video::Attr::new(
711+
common::video::TextForegroundColour::WHITE,
712+
common::video::TextBackgroundColour::BLACK,
713+
false,
714+
);
669715
for char_idx in 0..(80 * 60) {
670-
unsafe {
671-
// Blank
672-
FRAMEBUFFER[char_idx * 2] = b' ';
673-
// White on Black
674-
FRAMEBUFFER[(char_idx * 2) + 1] = 0xF0;
675-
}
716+
// Blank
717+
FRAMEBUFFER.write_at(char_idx * 2, b' ');
718+
// White on Black
719+
FRAMEBUFFER.write_at((char_idx * 2) + 1, white_on_black.as_u8());
676720
}
677721

678722
// Process args
@@ -926,11 +970,9 @@ extern "C" fn video_get_mode() -> common::video::Mode {
926970
/// to provide the 'basic' text buffer experience from reserves, so this
927971
/// function will never return `null` on start-up.
928972
extern "C" fn video_get_framebuffer() -> *mut u8 {
929-
unsafe {
930-
let p = FRAMEBUFFER.as_mut_ptr();
931-
debug!("video_get_framebuffer() -> {:p}", p);
932-
p
933-
}
973+
let p = FRAMEBUFFER.get_pointer();
974+
debug!("video_get_framebuffer() -> {:p}", p);
975+
p
934976
}
935977

936978
/// Set the framebuffer address.
@@ -1022,24 +1064,24 @@ fn convert_keycode(key: Key) -> common::hid::KeyCode {
10221064
match key {
10231065
Key::Backspace => common::hid::KeyCode::Backspace,
10241066
Key::Tab => common::hid::KeyCode::Tab,
1025-
Key::Return => common::hid::KeyCode::Enter,
1067+
Key::Return => common::hid::KeyCode::Return,
10261068
Key::Escape => common::hid::KeyCode::Escape,
10271069
Key::Space => common::hid::KeyCode::Spacebar,
10281070
// Key::Exclaim => common::hid::KeyCode::Exclaim,
10291071
// Key::Quotedbl => common::hid::KeyCode::Quotedbl,
1030-
// Key::Hash => common::hid::KeyCode::Hash,
1072+
Key::Hash => common::hid::KeyCode::Oem7,
10311073
// Key::Dollar => common::hid::KeyCode::Dollar,
10321074
// Key::Percent => common::hid::KeyCode::Percent,
10331075
// Key::Ampersand => common::hid::KeyCode::Ampersand,
1034-
// Key::Quote => common::hid::KeyCode::Quote,
1076+
Key::Quote => common::hid::KeyCode::Oem3,
10351077
// Key::LeftParen => common::hid::KeyCode::LeftParen,
10361078
// Key::RightParen => common::hid::KeyCode::RightParen,
10371079
// Key::Asterisk => common::hid::KeyCode::Asterisk,
10381080
// Key::Plus => common::hid::KeyCode::Plus,
1039-
Key::Comma => common::hid::KeyCode::Comma,
1040-
Key::Minus => common::hid::KeyCode::Minus,
1041-
Key::Period => common::hid::KeyCode::Fullstop,
1042-
Key::Slash => common::hid::KeyCode::Slash,
1081+
Key::Comma => common::hid::KeyCode::OemComma,
1082+
Key::Minus => common::hid::KeyCode::OemMinus,
1083+
Key::Period => common::hid::KeyCode::OemPeriod,
1084+
Key::Slash => common::hid::KeyCode::Oem2,
10431085
Key::Num0 => common::hid::KeyCode::Key0,
10441086
Key::Num1 => common::hid::KeyCode::Key1,
10451087
Key::Num2 => common::hid::KeyCode::Key2,
@@ -1051,18 +1093,18 @@ fn convert_keycode(key: Key) -> common::hid::KeyCode {
10511093
Key::Num8 => common::hid::KeyCode::Key8,
10521094
Key::Num9 => common::hid::KeyCode::Key9,
10531095
// Key::Colon => common::hid::KeyCode::Colon,
1054-
Key::Semicolon => common::hid::KeyCode::SemiColon,
1096+
Key::Semicolon => common::hid::KeyCode::Oem1,
10551097
// Key::Less => common::hid::KeyCode::Less,
1056-
Key::Equals => common::hid::KeyCode::Equals,
1098+
Key::Equals => common::hid::KeyCode::OemPlus,
10571099
// Key::Greater => common::hid::KeyCode::Greater,
10581100
// Key::Question => common::hid::KeyCode::Question,
10591101
// Key::At => common::hid::KeyCode::At,
1060-
// Key::LeftBracket => common::hid::KeyCode::LeftBracket,
1061-
// Key::Backslash => common::hid::KeyCode::Backslash,
1062-
// Key::RightBracket => common::hid::KeyCode::RightBracket,
1102+
Key::LeftBracket => common::hid::KeyCode::Oem4,
1103+
Key::Backslash => common::hid::KeyCode::Oem5,
1104+
Key::RightBracket => common::hid::KeyCode::Oem6,
10631105
// Key::Caret => common::hid::KeyCode::Caret,
10641106
// Key::Underscore => common::hid::KeyCode::Underscore,
1065-
// Key::Backquote => common::hid::KeyCode::Backquote,
1107+
Key::Backquote => common::hid::KeyCode::Oem8,
10661108
Key::A => common::hid::KeyCode::A,
10671109
Key::B => common::hid::KeyCode::B,
10681110
Key::C => common::hid::KeyCode::C,
@@ -1116,10 +1158,10 @@ fn convert_keycode(key: Key) -> common::hid::KeyCode {
11161158
Key::Down => common::hid::KeyCode::ArrowDown,
11171159
Key::Up => common::hid::KeyCode::ArrowUp,
11181160
Key::NumLock => common::hid::KeyCode::NumpadLock,
1119-
Key::KpDivide => common::hid::KeyCode::NumpadSlash,
1120-
Key::KpMultiply => common::hid::KeyCode::NumpadStar,
1121-
Key::KpMinus => common::hid::KeyCode::NumpadMinus,
1122-
Key::KpPlus => common::hid::KeyCode::NumpadPlus,
1161+
Key::KpDivide => common::hid::KeyCode::NumpadDivide,
1162+
Key::KpMultiply => common::hid::KeyCode::NumpadMultiply,
1163+
Key::KpMinus => common::hid::KeyCode::NumpadSubtract,
1164+
Key::KpPlus => common::hid::KeyCode::NumpadAdd,
11231165
Key::KpEnter => common::hid::KeyCode::NumpadEnter,
11241166
Key::Kp1 => common::hid::KeyCode::Numpad1,
11251167
Key::Kp2 => common::hid::KeyCode::Numpad2,
@@ -1134,14 +1176,14 @@ fn convert_keycode(key: Key) -> common::hid::KeyCode {
11341176
Key::KpPeriod => common::hid::KeyCode::NumpadPeriod,
11351177
// Key::KpEquals => common::hid::KeyCode::KpEquals,
11361178
// Key::KpComma => common::hid::KeyCode::KpComma,
1137-
Key::LCtrl => common::hid::KeyCode::ControlLeft,
1138-
Key::LShift => common::hid::KeyCode::ShiftLeft,
1139-
Key::LAlt => common::hid::KeyCode::AltLeft,
1140-
Key::LGui => common::hid::KeyCode::WindowsLeft,
1141-
Key::RCtrl => common::hid::KeyCode::ControlRight,
1142-
Key::RShift => common::hid::KeyCode::ShiftRight,
1143-
Key::RAlt => common::hid::KeyCode::AltRight,
1144-
Key::RGui => common::hid::KeyCode::WindowsRight,
1179+
Key::LCtrl => common::hid::KeyCode::LControl,
1180+
Key::LShift => common::hid::KeyCode::LShift,
1181+
Key::LAlt => common::hid::KeyCode::LAlt,
1182+
Key::LGui => common::hid::KeyCode::LWin,
1183+
Key::RCtrl => common::hid::KeyCode::RControl,
1184+
Key::RShift => common::hid::KeyCode::RShift,
1185+
Key::RAlt => common::hid::KeyCode::RAltGr,
1186+
Key::RGui => common::hid::KeyCode::RWin,
11451187
_ => common::hid::KeyCode::X,
11461188
}
11471189
}
@@ -1214,7 +1256,7 @@ unsafe extern "C" fn video_set_whole_palette(
12141256

12151257
extern "C" fn i2c_bus_get_info(_i2c_bus: u8) -> common::Option<common::i2c::BusInfo> {
12161258
debug!("i2c_bus_get_info");
1217-
unimplemented!();
1259+
common::Option::None
12181260
}
12191261

12201262
extern "C" fn i2c_write_read(
@@ -1225,69 +1267,68 @@ extern "C" fn i2c_write_read(
12251267
_rx: common::ApiBuffer,
12261268
) -> common::Result<()> {
12271269
debug!("i2c_write_read");
1228-
unimplemented!();
1270+
common::Result::Err(common::Error::Unimplemented)
12291271
}
12301272

12311273
extern "C" fn audio_mixer_channel_get_info(
12321274
_audio_mixer_id: u8,
1233-
) -> common::Result<common::audio::MixerChannelInfo> {
1275+
) -> common::Option<common::audio::MixerChannelInfo> {
12341276
debug!("audio_mixer_channel_get_info");
1235-
unimplemented!();
1277+
common::Option::None
12361278
}
12371279

12381280
extern "C" fn audio_mixer_channel_set_level(_audio_mixer_id: u8, _level: u8) -> common::Result<()> {
12391281
debug!("audio_mixer_channel_set_level");
1240-
unimplemented!();
1282+
common::Result::Err(common::Error::Unimplemented)
12411283
}
12421284

12431285
extern "C" fn audio_output_set_config(_config: common::audio::Config) -> common::Result<()> {
12441286
debug!("audio_output_set_config");
1245-
unimplemented!();
1287+
common::Result::Err(common::Error::Unimplemented)
12461288
}
12471289

12481290
extern "C" fn audio_output_get_config() -> common::Result<common::audio::Config> {
12491291
debug!("audio_output_get_config");
1250-
unimplemented!();
1292+
common::Result::Err(common::Error::Unimplemented)
12511293
}
12521294

12531295
unsafe extern "C" fn audio_output_data(_samples: common::ApiByteSlice) -> common::Result<usize> {
12541296
debug!("audio_output_data");
1255-
unimplemented!();
1297+
common::Result::Err(common::Error::Unimplemented)
12561298
}
12571299

12581300
extern "C" fn audio_output_get_space() -> common::Result<usize> {
12591301
debug!("audio_output_get_space");
1260-
unimplemented!();
1302+
common::Result::Err(common::Error::Unimplemented)
12611303
}
12621304

12631305
extern "C" fn audio_input_set_config(_config: common::audio::Config) -> common::Result<()> {
12641306
debug!("audio_input_set_config");
1265-
unimplemented!();
1307+
common::Result::Err(common::Error::Unimplemented)
12661308
}
12671309

12681310
extern "C" fn audio_input_get_config() -> common::Result<common::audio::Config> {
12691311
debug!("audio_input_get_config");
1270-
unimplemented!();
1312+
common::Result::Err(common::Error::Unimplemented)
12711313
}
12721314

12731315
extern "C" fn audio_input_data(_samples: common::ApiBuffer) -> common::Result<usize> {
12741316
debug!("audio_input_data");
1275-
unimplemented!();
1317+
common::Result::Err(common::Error::Unimplemented)
12761318
}
12771319

12781320
extern "C" fn audio_input_get_count() -> common::Result<usize> {
12791321
debug!("audio_input_get_count");
1280-
unimplemented!();
1322+
common::Result::Err(common::Error::Unimplemented)
12811323
}
12821324

12831325
extern "C" fn bus_select(_periperal_id: common::Option<u8>) {
12841326
debug!("bus_select");
1285-
unimplemented!();
12861327
}
12871328

12881329
extern "C" fn bus_get_info(_periperal_id: u8) -> common::Option<common::bus::PeripheralInfo> {
12891330
debug!("bus_get_info");
1290-
unimplemented!();
1331+
common::Option::None
12911332
}
12921333

12931334
extern "C" fn bus_write_read(
@@ -1296,12 +1337,12 @@ extern "C" fn bus_write_read(
12961337
_rx: common::ApiBuffer,
12971338
) -> common::Result<()> {
12981339
debug!("bus_write_read");
1299-
unimplemented!();
1340+
common::Result::Err(common::Error::Unimplemented)
13001341
}
13011342

13021343
extern "C" fn bus_exchange(_buffer: common::ApiBuffer) -> common::Result<()> {
13031344
debug!("bus_exchange");
1304-
unimplemented!();
1345+
common::Result::Err(common::Error::Unimplemented)
13051346
}
13061347

13071348
extern "C" fn time_ticks_get() -> common::Ticks {
@@ -1508,10 +1549,10 @@ impl AppState for MyApp {
15081549
let byte_offset = usize::from(cell_no) * 2;
15091550
let x = col * 8;
15101551
let y = row * font_height;
1511-
let glyph = unsafe { *FRAMEBUFFER.get_unchecked(byte_offset) };
1512-
let attr = unsafe { *FRAMEBUFFER.get_unchecked(byte_offset + 1) };
1513-
let fg_idx = (attr >> 3) & 0b1111;
1514-
let bg_idx = attr & 0b111;
1552+
let glyph = FRAMEBUFFER.get_at(byte_offset);
1553+
let attr = common::video::Attr(FRAMEBUFFER.get_at(byte_offset + 1));
1554+
let fg_idx = attr.fg().as_u8();
1555+
let bg_idx = attr.bg().as_u8();
15151556
let bg =
15161557
RGBColour::from_packed(PALETTE[usize::from(bg_idx)].load(Ordering::SeqCst));
15171558
let glyph_box = rect!(i32::from(x), i32::from(y), 8i32, font_height as i32,);

0 commit comments

Comments
 (0)