Skip to content

Commit f1ea66b

Browse files
committed
Merge branch 'master' of https://github.com/funmaker/iepass
2 parents 1d16e40 + 42f7ffb commit f1ea66b

6 files changed

Lines changed: 93 additions & 23 deletions

File tree

p8rs-log/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ cfg_if::cfg_if! {
168168

169169
cfg_if::cfg_if! {
170170
if #[cfg(feature = "defmt")] {
171-
pub use defmt::eprintln;
171+
pub use defmt::error as eprintln;
172172
} else if #[cfg(all(feature = "std", feature = "std-error"))] {
173173
pub use std::eprintln;
174174
} else if #[cfg(feature = "log-04")] {

p8rs-macros/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use syn::parse_macro_input;
33

44
mod p8;
55
mod api;
6+
mod transparent_ref;
67

78
#[proc_macro]
89
pub fn p8(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -20,3 +21,11 @@ pub fn api_callback(_attr: proc_macro::TokenStream, item: proc_macro::TokenStrea
2021
#callback
2122
).into()
2223
}
24+
25+
#[proc_macro_derive(TransparentRef)]
26+
pub fn derive_transparent_ref(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
27+
let item = parse_macro_input!(item as syn::DeriveInput);
28+
let derive = transparent_ref::make_derive(&item).unwrap_or_else(syn::Error::into_compile_error);
29+
30+
derive.into_token_stream().into()
31+
}

p8rs-macros/src/transparent_ref.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote;
3+
use syn::{Data, Fields};
4+
5+
pub fn make_derive(item: &syn::DeriveInput) -> syn::Result<TokenStream> {
6+
let mut is_transparent = false;
7+
for attr in &item.attrs {
8+
if attr.path().is_ident("repr") {
9+
attr.parse_nested_meta(|meta| {
10+
if meta.path.is_ident("transparent") {
11+
is_transparent = true;
12+
Ok(())
13+
} else {
14+
Err(meta.error("expected `#[repr(transparent)]`"))
15+
}
16+
})?;
17+
}
18+
}
19+
20+
if !is_transparent {
21+
return Err(syn::Error::new(item.ident.span(), "Item must be `#[repr(transparent)]`"));
22+
}
23+
24+
let item_struct = match &item.data {
25+
Data::Struct(item_struct) => item_struct,
26+
_ => return Err(syn::Error::new(item.ident.span(), "Item must be a struct")),
27+
};
28+
29+
let field = match &item_struct.fields {
30+
Fields::Named(fields) if fields.named.len() == 1 => &fields.named[0],
31+
Fields::Unnamed(fields) if fields.unnamed.len() == 1 => &fields.unnamed[0],
32+
_ => return Err(syn::Error::new(item.ident.span(), "Struct must have single field"))
33+
};
34+
35+
let ident = &item.ident;
36+
let bits_type = &field.ty;
37+
38+
Ok(quote!{
39+
impl #ident {
40+
fn from_bits_ref(inner: &#bits_type) -> &Self {
41+
unsafe { ::core::mem::transmute(inner) }
42+
}
43+
fn from_bits_mut(inner: &mut #bits_type) -> &mut Self {
44+
unsafe { ::core::mem::transmute(inner) }
45+
}
46+
fn from_bits_boxed<A: ::core::alloc::Allocator>(inner: Box<#bits_type, A>) -> Box<Self, A> {
47+
let (ptr, alloc) = Box::into_raw_with_allocator(inner);
48+
unsafe { Box::from_raw_in(ptr as *mut Self, alloc) }
49+
}
50+
fn to_bits_ref(&self) -> &#bits_type {
51+
unsafe { ::core::mem::transmute(self) }
52+
}
53+
fn to_bits_mut(&mut self) -> &mut #bits_type {
54+
unsafe { ::core::mem::transmute(self) }
55+
}
56+
fn to_bits_boxed<A: ::core::alloc::Allocator>(self: Box<Self, A>) -> Box<#bits_type, A> {
57+
let (ptr, alloc) = Box::into_raw_with_allocator(self);
58+
unsafe { Box::from_raw_in(ptr as *mut #bits_type, alloc) }
59+
}
60+
}
61+
})
62+
}

p8rs/src/vm/api/print.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn install_pico8_print<A: Allocator + 'static>(ctx: Context) {
4545
}
4646
};
4747

48-
let flags = rt.memory.machine_state().get_print_defaults();
48+
let flags = *rt.memory.machine_state().print_defaults();
4949

5050
if y.is_none() {
5151
let font_height = get_font_height(rt, flags);

p8rs/src/vm/memory/machine_state.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::ops::{Deref, DerefMut};
22
use bitflags::bitflags;
3-
3+
use p8rs_macros::TransparentRef;
44
use super::MemoryAccess;
55

66
/// 0x5f00..=0x5f80
@@ -60,20 +60,12 @@ impl MachineState<'_> {
6060
(&mut self[0x20..=0x23]).try_into().unwrap()
6161
}
6262

63-
pub fn get_misc_chipset_flags(&self) -> MiscChipsetFeatureFlags {
64-
MiscChipsetFeatureFlags::from_bits_truncate(self[0x36])
65-
}
66-
67-
pub fn set_misc_chipset_flags(&mut self, flags: MiscChipsetFeatureFlags) {
68-
self[0x36] = flags.bits()
63+
pub fn misc_chipset_flags(&mut self) -> &mut MiscChipsetFeatureFlags {
64+
MiscChipsetFeatureFlags::from_bits_mut(&mut self[0x36])
6965
}
7066

71-
pub fn get_print_defaults(&self) -> PrintAttributeFlags {
72-
PrintAttributeFlags::from_bits_truncate(self[0x58])
73-
}
74-
75-
pub fn set_print_defaults(&mut self, flags: PrintAttributeFlags) {
76-
self[0x58] = flags.bits();
67+
pub fn print_defaults(&mut self) -> &mut PrintAttributeFlags {
68+
PrintAttributeFlags::from_bits_mut(&mut self[0x58])
7769
}
7870

7971
pub fn sprite_addr_map(&mut self) -> &mut u8 {
@@ -134,9 +126,16 @@ impl Palette {
134126
}
135127
}
136128

129+
#[derive(Copy, Clone, Debug, PartialEq, Eq, TransparentRef)]
130+
#[repr(transparent)]
131+
pub struct PrintAttributeFlags(u8);
132+
133+
#[derive(Copy, Clone, Debug, PartialEq, Eq, TransparentRef)]
134+
#[repr(transparent)]
135+
pub struct MiscChipsetFeatureFlags(u8);
136+
137137
bitflags! {
138-
#[derive(Copy, Clone)]
139-
pub struct PrintAttributeFlags: u8 {
138+
impl PrintAttributeFlags: u8 {
140139
const ENABLE = 1 << 0;
141140
const PADDING = 1 << 1;
142141
const WIDE = 1 << 2;
@@ -147,9 +146,8 @@ bitflags! {
147146
const CUSTOM_FONT = 1 << 7;
148147
}
149148

150-
#[derive(Copy, Clone)]
151-
pub struct MiscChipsetFeatureFlags: u8 {
152-
/// the undocumented multi-screen feature is enabled
149+
impl MiscChipsetFeatureFlags: u8 {
150+
/// the undocumented multiscreen feature is enabled
153151
const MULTI_SCREEN = 1 << 0;
154152
/// the diameter of circles drawn using circ() and circfill() will be increased by 1 pixel rightward and 1 pixel downward if the fractional part of the radius is .5 or greater
155153
const FRACT_CIRCLE = 1 << 1;

p8rs/src/vm/memory/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use core::ops::{Deref, DerefMut};
33
use alloc::boxed::Box;
44
use alloc::alloc::Global;
55
use p8rs_types::p8num::P8Num;
6+
use p8rs_macros::TransparentRef;
67

78
pub mod sprites;
89
pub mod map;
@@ -11,15 +12,16 @@ pub mod sound_effects;
1112
pub mod machine_state;
1213
pub mod screen;
1314

15+
use crate::utils;
1416
use sprites::Sprites;
1517
use map::Map;
1618
use music::Music;
1719
use sound_effects::SoundEffects;
1820
use machine_state::MachineState;
1921
use screen::Screen;
2022

23+
#[derive(Debug, Clone, TransparentRef)]
2124
#[repr(transparent)]
22-
#[derive(Debug)]
2325
pub struct Memory([u8; 0x10000]);
2426

2527
impl Memory {
@@ -28,8 +30,7 @@ impl Memory {
2830
}
2931

3032
pub fn new_in<A: Allocator>(alloc: A) -> Box<Self, A> {
31-
// SAFETY: Memory is just a transparent, u8 array.
32-
let mut mem = unsafe { Box::<Self, A>::new_zeroed_in(alloc).assume_init() };
33+
let mut mem = Memory::from_bits_boxed(utils::new_zeroed_box_in(alloc));
3334

3435
mem.reset();
3536

0 commit comments

Comments
 (0)