Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
2a15eb1122 | |||
537bcad73b | |||
101c513838 | |||
eb86e33117 | |||
f250eee2ea | |||
6b6b2211a8 | |||
6fefd600e1 | |||
aff5103636 | |||
b166e9c004 | |||
4b15253580 | |||
20c90af201 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -58,7 +58,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byte-pusher-emu"
|
name = "byte-pusher-emu"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"clap",
|
"clap",
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "byte-pusher-emu"
|
name = "byte-pusher-emu"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
license = "BSD-3"
|
||||||
|
authors = ["chrisvrose"]
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
@@ -14,3 +17,4 @@ sdl2 = "0.36.0"
|
|||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
lto = true
|
||||||
|
28
LICENSE
Normal file
28
LICENSE
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2024, Atreya Bain
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
45
README.md
45
README.md
@@ -1,27 +1,32 @@
|
|||||||
# BytePusher Emulator
|
# BytePusher Emulator
|
||||||
|
|
||||||
This is a play at emulating a BytePusher machine developed by [Javamannen](https://esolangs.org/wiki/User:Javamannen).
|
`byte-pusher-emu` is an emulator for the BytePusher virtual machine developed by [Javamannen](https://esolangs.org/wiki/User:Javamannen).
|
||||||
Binary builds for linux x86_64 is available in GitHub Action runs.
|
|
||||||
|
|
||||||
|
Binary builds for linux x86_64 is available in the Releases section.
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>More screenshots</summary>
|
||||||
|
|
||||||
|
#### Palette Test
|
||||||

|

|
||||||
Screenshot program author: [Javamannen](https://esolangs.org/wiki/User:Javamannen)
|
|
||||||
|
|
||||||
## Status
|
#### Keyboard test
|
||||||
|

|
||||||
|
|
||||||
- [X] Memory
|
</details>
|
||||||
- [X] Color
|
|
||||||
- [X] CPU
|
The roms showcased here have been created by [Javamannen](https://esolangs.org/wiki/User:Javamannen).
|
||||||
- [X] Inner loop - 65536 instructions
|
|
||||||
- [X] Outer loop - 60fps display loop
|
Note: This is a project that was used to learn Rust and emulation basics. However, it should work good as a reference for running ROMs.
|
||||||
- [X] Display adapter
|
|
||||||
- [X] SDL2 adapter
|
|
||||||
- [X] Keyboard
|
|
||||||
- [X] Audio
|
|
||||||
- [X] Load a ROM
|
|
||||||
|
|
||||||
## Usage instructions
|
## Usage instructions
|
||||||
|
|
||||||
For help on how to use, please refer
|
`byte-pusher-emu` is rather minimalistic, and needs to be launched from CLI.
|
||||||
|
|
||||||
|
For help on how to use, run the following:
|
||||||
```sh
|
```sh
|
||||||
./byte-pusher-emu --help
|
./byte-pusher-emu --help
|
||||||
```
|
```
|
||||||
@@ -37,3 +42,13 @@ Loads a rom from the file specified. If `-f` is not mentioned, the VM will run w
|
|||||||
## More information about the BytePusher VM
|
## More information about the BytePusher VM
|
||||||
|
|
||||||
https://esolangs.org/wiki/BytePusher
|
https://esolangs.org/wiki/BytePusher
|
||||||
|
|
||||||
|
## Development Status
|
||||||
|
|
||||||
|
- [X] Memory
|
||||||
|
- [X] Color
|
||||||
|
- [X] CPU
|
||||||
|
- [X] Display adapter - SDL2
|
||||||
|
- [X] Keyboard - SDL2
|
||||||
|
- [X] Audio - SDL2
|
||||||
|
- [X] Load a ROM
|
BIN
assets/audio_test.png
Normal file
BIN
assets/audio_test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
BIN
assets/kb_test.png
Normal file
BIN
assets/kb_test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 8.4 KiB |
12
src/args.rs
12
src/args.rs
@@ -1,8 +1,10 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
#[derive(Debug,Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(version, about, long_about = "Byte Pusher Emulator")]
|
#[command(version, about, author)]
|
||||||
pub struct BytePusherArgs{
|
pub struct BytePusherArgs {
|
||||||
#[arg(short,long)]
|
#[arg(short, long, help = "ROM file to load")]
|
||||||
pub file_name:Option<String>
|
pub file_name: Option<String>,
|
||||||
|
#[arg(short, long, help = "Scale at which to draw", default_value_t = 2.0)]
|
||||||
|
pub draw_scale: f32,
|
||||||
}
|
}
|
@@ -8,7 +8,10 @@ use crate::misc::error::EmulatorError;
|
|||||||
use crate::misc::result::EmulatorResult;
|
use crate::misc::result::EmulatorResult;
|
||||||
|
|
||||||
pub const AUDIO_BUFFER_SIZE: usize = 256;
|
pub const AUDIO_BUFFER_SIZE: usize = 256;
|
||||||
|
const I8_SIGN_BYTE: u8 = 0x80;
|
||||||
|
const AUDIO_REG_START: usize = 6;
|
||||||
|
const AUDIO_REG_LEN: usize = 2;
|
||||||
|
const AUDIO_REG_END: usize = AUDIO_REG_START + AUDIO_REG_LEN -1;
|
||||||
|
|
||||||
pub struct AudioProcessor<'a> {
|
pub struct AudioProcessor<'a> {
|
||||||
ram: &'a RamMemory,
|
ram: &'a RamMemory,
|
||||||
@@ -31,6 +34,7 @@ impl<'a> AudioProcessor<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> AudioProcessor<'a> {
|
impl<'a> AudioProcessor<'a> {
|
||||||
pub fn queue(&mut self) -> EmulatorResult<()> {
|
pub fn queue(&mut self) -> EmulatorResult<()> {
|
||||||
let audio_base_reg = (self.get_audio_base_reg() as u32) << 8;
|
let audio_base_reg = (self.get_audio_base_reg() as u32) << 8;
|
||||||
@@ -39,22 +43,22 @@ impl<'a> AudioProcessor<'a> {
|
|||||||
// The CPU frame timing is just a little less than 60 fps to prevent audio stutter.
|
// The CPU frame timing is just a little less than 60 fps to prevent audio stutter.
|
||||||
// We will then wait for audio to drain to adjust frame timing
|
// We will then wait for audio to drain to adjust frame timing
|
||||||
if self.audio_queue.size() == 0 {
|
if self.audio_queue.size() == 0 {
|
||||||
log::trace!("Detected Queue empty!");
|
log::info!("Detected Queue empty! Audio stutter may occur");
|
||||||
}
|
}
|
||||||
while self.audio_queue.size() > 32 {
|
while self.audio_queue.size() > (AUDIO_BUFFER_SIZE / 2) as u32 {
|
||||||
::std::thread::sleep(Duration::from_micros(1))
|
std::thread::sleep(Duration::from_micros(1))
|
||||||
}
|
}
|
||||||
self.ram.try_copy_block(audio_base_reg, fb)?;
|
self.ram.try_copy_block(audio_base_reg, fb)?;
|
||||||
|
|
||||||
//convert to u8 audio format (Bytepusher stores it as "i8")
|
//convert to u8 audio format (BytePusher stores it as "i8")
|
||||||
fb.iter_mut().for_each(|item|{
|
fb.iter_mut().for_each(|item|{
|
||||||
*item^= 0x80;
|
*item ^= I8_SIGN_BYTE;
|
||||||
});
|
});
|
||||||
self.audio_queue.queue_audio(fb).map_err(|s| { EmulatorError::OtherError(Some(AUDIO), s) })
|
self.audio_queue.queue_audio(fb).map_err(|s| { EmulatorError::OtherError(Some(AUDIO), s) })
|
||||||
}
|
}
|
||||||
fn get_audio_base_reg(&self) -> u16 {
|
fn get_audio_base_reg(&self) -> u16 {
|
||||||
let data = self.ram.get_data_ref();
|
let data = self.ram.get_data_ref();
|
||||||
let audio_base_reg = data.get(6..8).unwrap();
|
let audio_base_reg = data.get(AUDIO_REG_START..=AUDIO_REG_END).unwrap();
|
||||||
read_big_endian_u16(audio_base_reg.try_into().unwrap())
|
read_big_endian_u16(audio_base_reg.try_into().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -40,7 +40,6 @@ impl<'a> Cpu<'a> {
|
|||||||
|
|
||||||
log::trace!("Finished internal loop");
|
log::trace!("Finished internal loop");
|
||||||
self.graphics_processor.draw()?;
|
self.graphics_processor.draw()?;
|
||||||
// TODO send audio
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,8 @@ use crate::misc::error::DeviceType::GRAPHICS;
|
|||||||
use crate::misc::error::EmulatorError;
|
use crate::misc::error::EmulatorError;
|
||||||
use crate::misc::result::EmulatorResult;
|
use crate::misc::result::EmulatorResult;
|
||||||
|
|
||||||
pub const DEVICE_FRAMEBUFFER_SIZE: usize = 256 * 256;
|
pub const DEVICE_RESOLUTION: usize = 256;
|
||||||
|
pub const DEVICE_FRAMEBUFFER_SIZE: usize = DEVICE_RESOLUTION * DEVICE_RESOLUTION;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GraphicsProcessor<'a> {
|
pub struct GraphicsProcessor<'a> {
|
||||||
|
@@ -19,12 +19,12 @@ impl<'a> Keyboard<'a>{
|
|||||||
|
|
||||||
pub fn key_down(&mut self,x:u8){
|
pub fn key_down(&mut self,x:u8){
|
||||||
self.bitflags |= 1<<x;
|
self.bitflags |= 1<<x;
|
||||||
log::debug!("Key Down, keyboard state {}",self.bitflags);
|
log::trace!("Key Down - state {}",self.bitflags);
|
||||||
self.dirty = true
|
self.dirty = true
|
||||||
}
|
}
|
||||||
pub fn key_up(&mut self,x:u8){
|
pub fn key_up(&mut self,x:u8){
|
||||||
self.bitflags &= !((1<<x) as u16);
|
self.bitflags &= !((1<<x) as u16);
|
||||||
log::debug!("Key Up, keyboard state {}",self.bitflags);
|
log::debug!("Key Up - state {}",self.bitflags);
|
||||||
self.dirty = true
|
self.dirty = true
|
||||||
}
|
}
|
||||||
pub fn flush_keyboard(&mut self)->EmulatorResult<()>{
|
pub fn flush_keyboard(&mut self)->EmulatorResult<()>{
|
||||||
|
@@ -53,6 +53,7 @@ impl RamMemory {
|
|||||||
pub fn get_data_ref(&self) -> Ref<Box<[u8; MEM_LENGTH]>> {
|
pub fn get_data_ref(&self) -> Ref<Box<[u8; MEM_LENGTH]>> {
|
||||||
self.data.borrow()
|
self.data.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memory for RamMemory {
|
impl Memory for RamMemory {
|
||||||
|
@@ -21,7 +21,7 @@ impl<'a> Debug for SDLGraphicsAdapter<'a> {
|
|||||||
|
|
||||||
impl<'a> SDLGraphicsAdapter<'a> {
|
impl<'a> SDLGraphicsAdapter<'a> {
|
||||||
pub fn new(graphics_processor: &'a GraphicsProcessor) -> SDLGraphicsAdapter<'a> {
|
pub fn new(graphics_processor: &'a GraphicsProcessor) -> SDLGraphicsAdapter<'a> {
|
||||||
let color_fb_vec = vec![0u8; DEVICE_FRAMEBUFFER_SIZE * 3].into_boxed_slice().try_into().expect("???");
|
let color_fb_vec = vec![0u8; DEVICE_FRAMEBUFFER_SIZE * 3].into_boxed_slice().try_into().expect("Failed conversion");
|
||||||
SDLGraphicsAdapter {
|
SDLGraphicsAdapter {
|
||||||
color_fb: color_fb_vec,
|
color_fb: color_fb_vec,
|
||||||
graphics_processor,
|
graphics_processor,
|
||||||
@@ -37,8 +37,8 @@ impl<'a> SDLGraphicsAdapter<'a> {
|
|||||||
let mut texture = texture_creator.create_texture(PixelFormatEnum::RGB24, TextureAccess::Streaming, 256, 256).expect("Failed to make texture");
|
let mut texture = texture_creator.create_texture(PixelFormatEnum::RGB24, TextureAccess::Streaming, 256, 256).expect("Failed to make texture");
|
||||||
texture.with_lock(None, |f, _i| {
|
texture.with_lock(None, |f, _i| {
|
||||||
f.copy_from_slice(self.color_fb.as_ref())
|
f.copy_from_slice(self.color_fb.as_ref())
|
||||||
}).expect("TODO: panic message");
|
})?;
|
||||||
canvas.copy(&texture, None, None).expect("Failed to write texture");
|
canvas.copy(&texture, None, None)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
39
src/main.rs
39
src/main.rs
@@ -13,7 +13,7 @@ use simple_logger::SimpleLogger;
|
|||||||
use crate::args::BytePusherArgs;
|
use crate::args::BytePusherArgs;
|
||||||
use crate::emu::audio::AudioProcessor;
|
use crate::emu::audio::AudioProcessor;
|
||||||
use crate::emu::cpu::Cpu;
|
use crate::emu::cpu::Cpu;
|
||||||
use crate::emu::graphics::GraphicsProcessor;
|
use crate::emu::graphics::{DEVICE_RESOLUTION, GraphicsProcessor};
|
||||||
use crate::emu::keyboard::Keyboard;
|
use crate::emu::keyboard::Keyboard;
|
||||||
use crate::emu::memory::{MEM_LENGTH, RamMemory};
|
use crate::emu::memory::{MEM_LENGTH, RamMemory};
|
||||||
use crate::graphics::graphics_adapter::SDLGraphicsAdapter;
|
use crate::graphics::graphics_adapter::SDLGraphicsAdapter;
|
||||||
@@ -26,14 +26,12 @@ mod misc;
|
|||||||
mod graphics;
|
mod graphics;
|
||||||
|
|
||||||
fn main() -> EmulatorResult<()> {
|
fn main() -> EmulatorResult<()> {
|
||||||
let BytePusherArgs { file_name } = BytePusherArgs::parse();
|
let BytePusherArgs { file_name ,draw_scale} = BytePusherArgs::parse();
|
||||||
SimpleLogger::new().with_level(LevelFilter::Info).env().init().unwrap();
|
SimpleLogger::new().with_level(LevelFilter::Info).env().init()?;
|
||||||
|
|
||||||
|
let (file_bytes, ..) = try_load_rom(&file_name)?;
|
||||||
|
|
||||||
let (file_bytes, x) = try_load_rom(&file_name)?;
|
let (mut canvas, mut event_pump, audio_queue) = initiate_sdl(draw_scale);
|
||||||
assert!(x < MEM_LENGTH);
|
|
||||||
|
|
||||||
let (mut canvas, mut event_pump, audio_queue) = initiate_sdl();
|
|
||||||
|
|
||||||
|
|
||||||
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
||||||
@@ -44,9 +42,9 @@ fn main() -> EmulatorResult<()> {
|
|||||||
|
|
||||||
let mut sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor);
|
let mut sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor);
|
||||||
|
|
||||||
|
canvas.set_draw_color(Color::BLACK);
|
||||||
|
canvas.clear();
|
||||||
'running: loop {
|
'running: loop {
|
||||||
canvas.set_draw_color(Color::BLACK);
|
|
||||||
canvas.clear();
|
|
||||||
for event in event_pump.poll_iter() {
|
for event in event_pump.poll_iter() {
|
||||||
match event {
|
match event {
|
||||||
Event::Quit { .. } |
|
Event::Quit { .. } |
|
||||||
@@ -71,15 +69,14 @@ fn main() -> EmulatorResult<()> {
|
|||||||
|
|
||||||
// The rest of the game loop goes here...
|
// The rest of the game loop goes here...
|
||||||
cpu.cycle()?;
|
cpu.cycle()?;
|
||||||
// draw graphics
|
|
||||||
sdl2_graphics_adapter.draw(&mut canvas)?;
|
|
||||||
// TODO render audio
|
|
||||||
audio_processor.queue()?;
|
|
||||||
|
|
||||||
|
sdl2_graphics_adapter.draw(&mut canvas)?;
|
||||||
|
audio_processor.queue()?;
|
||||||
canvas.present();
|
canvas.present();
|
||||||
|
|
||||||
|
|
||||||
// 60fps - small offset to consider for cpu cycle time
|
// 60fps - small offset to consider for cpu cycle time
|
||||||
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60 - 2000_000));
|
std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60 - 2000_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -121,10 +118,8 @@ fn try_load_rom(file_name_option: &Option<String>) -> EmulatorResult<(Vec<u8>, u
|
|||||||
Ok((file_bytes, bytes_read))
|
Ok((file_bytes, bytes_read))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initiate_sdl() -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
fn initiate_sdl(draw_scale:f32) -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
||||||
const BASE_RESOLUTION: u32 = 256;
|
let window_resolution: u32 = (DEVICE_RESOLUTION as f32 * draw_scale) as u32;
|
||||||
const DRAW_FACTOR: u32 = 4;
|
|
||||||
const WINDOW_RESOLUTION: u32 = BASE_RESOLUTION * DRAW_FACTOR;
|
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
let audio_subsystem = sdl_context.audio().unwrap();
|
let audio_subsystem = sdl_context.audio().unwrap();
|
||||||
@@ -137,18 +132,16 @@ fn initiate_sdl() -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
|||||||
audio_queue.resume();
|
audio_queue.resume();
|
||||||
|
|
||||||
|
|
||||||
let window = video_subsystem.window("byte-pusher-emu", WINDOW_RESOLUTION, WINDOW_RESOLUTION)
|
let window = video_subsystem.window("byte-pusher-emu", window_resolution, window_resolution)
|
||||||
.position_centered()
|
.position_centered()
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut canvas = window.into_canvas().build().unwrap();
|
let mut canvas = window.into_canvas().build().unwrap();
|
||||||
|
|
||||||
canvas.set_draw_color(Color::RGB(0x10, 0x10, 0x10));
|
canvas.set_scale(draw_scale, draw_scale).expect("Setting scale");
|
||||||
canvas.set_integer_scale(true).expect("Setting int scale");
|
|
||||||
|
|
||||||
canvas.set_scale(DRAW_FACTOR as f32, DRAW_FACTOR as f32).expect("Setting scale");
|
|
||||||
canvas.clear();
|
|
||||||
canvas.set_blend_mode(BlendMode::None);
|
canvas.set_blend_mode(BlendMode::None);
|
||||||
|
canvas.clear();
|
||||||
canvas.present();
|
canvas.present();
|
||||||
let event_pump = sdl_context.event_pump().unwrap();
|
let event_pump = sdl_context.event_pump().unwrap();
|
||||||
(canvas, event_pump, audio_queue)
|
(canvas, event_pump, audio_queue)
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
use std::array::TryFromSliceError;
|
use std::array::TryFromSliceError;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
|
use log::SetLoggerError;
|
||||||
use crate::misc::error::EmulatorError::EmulatorIOError;
|
use crate::misc::error::EmulatorError::EmulatorIOError;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -24,12 +25,23 @@ impl From<TryFromSliceError> for EmulatorError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for EmulatorError {
|
impl From<Error> for EmulatorError {
|
||||||
fn from(value: Error) -> Self {
|
fn from(value: Error) -> Self {
|
||||||
EmulatorIOError(value)
|
EmulatorIOError(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<SetLoggerError> for EmulatorError{
|
||||||
|
fn from(value: SetLoggerError) -> Self {
|
||||||
|
EmulatorError::OtherError(None,format!("Logger allocation failed! Error: {}",value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<String> for EmulatorError{
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
EmulatorError::OtherError(None,value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user