2023-03-27 18:30:31 -05:00
|
|
|
// (c) 2023 John A. Breaux
|
|
|
|
// This code is licensed under MIT license (see LICENSE.txt for details)
|
|
|
|
|
2023-03-29 12:29:07 -05:00
|
|
|
//! Error type for Chirp
|
Initial commit:
Created outline of emulator:
The emulator has a Bus, which attaches a CPU to some Memory (Mapped Devices)
The design isn't particularly efficient, but the interpreter only needs to
run at ~500Hz or so. It's Rust. It can do that.
Instructions yet to be implemented:
Cxbb: "Store a random number, masked by bitmask bb, into vX"
Dxyn: "Draw an 8 by n sprite to the screen at coordinates (x, y)"
Fx0A: "Wait for a key, then set vX to the value of the pressed key"
Fx33: "BCD convert X, storing the results in &I[0..3]"
Thoughts going forward:
- It's probably a good idea to parse instructions out into an enum.
I had this in an earlier design, but it didn't really look that good.
However, I haven't read many other emulators before, so I don't know the
style people generally go for.
- I haven't used a native graphics library before, and my cg class was done
entirely in a web browser. That kinda sucks, honestly. Sure the skill
might transfer well, but, >JS
2023-03-08 06:07:33 -06:00
|
|
|
|
2023-03-30 08:27:06 -05:00
|
|
|
use std::ops::Range;
|
|
|
|
|
2023-03-29 23:42:41 -05:00
|
|
|
use crate::bus::Region;
|
Initial commit:
Created outline of emulator:
The emulator has a Bus, which attaches a CPU to some Memory (Mapped Devices)
The design isn't particularly efficient, but the interpreter only needs to
run at ~500Hz or so. It's Rust. It can do that.
Instructions yet to be implemented:
Cxbb: "Store a random number, masked by bitmask bb, into vX"
Dxyn: "Draw an 8 by n sprite to the screen at coordinates (x, y)"
Fx0A: "Wait for a key, then set vX to the value of the pressed key"
Fx33: "BCD convert X, storing the results in &I[0..3]"
Thoughts going forward:
- It's probably a good idea to parse instructions out into an enum.
I had this in an earlier design, but it didn't really look that good.
However, I haven't read many other emulators before, so I don't know the
style people generally go for.
- I haven't used a native graphics library before, and my cg class was done
entirely in a web browser. That kinda sucks, honestly. Sure the skill
might transfer well, but, >JS
2023-03-08 06:07:33 -06:00
|
|
|
use thiserror::Error;
|
|
|
|
|
2023-03-29 23:45:39 -05:00
|
|
|
/// Result type, equivalent to [std::result::Result]<T, [enum@Error]>
|
Initial commit:
Created outline of emulator:
The emulator has a Bus, which attaches a CPU to some Memory (Mapped Devices)
The design isn't particularly efficient, but the interpreter only needs to
run at ~500Hz or so. It's Rust. It can do that.
Instructions yet to be implemented:
Cxbb: "Store a random number, masked by bitmask bb, into vX"
Dxyn: "Draw an 8 by n sprite to the screen at coordinates (x, y)"
Fx0A: "Wait for a key, then set vX to the value of the pressed key"
Fx33: "BCD convert X, storing the results in &I[0..3]"
Thoughts going forward:
- It's probably a good idea to parse instructions out into an enum.
I had this in an earlier design, but it didn't really look that good.
However, I haven't read many other emulators before, so I don't know the
style people generally go for.
- I haven't used a native graphics library before, and my cg class was done
entirely in a web browser. That kinda sucks, honestly. Sure the skill
might transfer well, but, >JS
2023-03-08 06:07:33 -06:00
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
2023-03-28 07:35:18 -05:00
|
|
|
|
2023-03-29 23:45:39 -05:00
|
|
|
/// Error type for Chirp.
|
I/O: KISS the bus, attach a screen, plug in a controller
Chip-8 has no ROM, nor memory management.
- It's much easier to just use contiguous memory.
- Then we can return references to slices of that memory
- ~3x speed increase
Screen exists now, uses 24-bit framebuffer
- We have a 1-bit framebuffer
- I chose colors that look good to me
Controller exists as well, has 16 buttons
- Mapped "0 123 456 789 ab cdef" to (QWERTY) "X 123 QWE ASD zC 4RFV"
- Other chip-8 interpreters may use a different layout
- This is good enough for now.
- F1-F9 map to control functions
- F1, F2: Dump CPU registers/screen contents
- F3, F4: Toggle disassembly/pause
- F5: Single-step the CPU, pausing after
- F6, F7: Set/Unset breakpoint
- F8, F9: Soft/Hard Reset CPU
2023-03-22 15:03:53 -05:00
|
|
|
#[derive(Debug, Error)]
|
Initial commit:
Created outline of emulator:
The emulator has a Bus, which attaches a CPU to some Memory (Mapped Devices)
The design isn't particularly efficient, but the interpreter only needs to
run at ~500Hz or so. It's Rust. It can do that.
Instructions yet to be implemented:
Cxbb: "Store a random number, masked by bitmask bb, into vX"
Dxyn: "Draw an 8 by n sprite to the screen at coordinates (x, y)"
Fx0A: "Wait for a key, then set vX to the value of the pressed key"
Fx33: "BCD convert X, storing the results in &I[0..3]"
Thoughts going forward:
- It's probably a good idea to parse instructions out into an enum.
I had this in an earlier design, but it didn't really look that good.
However, I haven't read many other emulators before, so I don't know the
style people generally go for.
- I haven't used a native graphics library before, and my cg class was done
entirely in a web browser. That kinda sucks, honestly. Sure the skill
might transfer well, but, >JS
2023-03-08 06:07:33 -06:00
|
|
|
pub enum Error {
|
2023-04-01 02:31:51 -05:00
|
|
|
/// Represents a breakpoint being hit
|
|
|
|
#[error("Breakpoint hit: {addr:03x} ({next:04x})")]
|
|
|
|
BreakpointHit {
|
|
|
|
/// The address of the breakpoint
|
|
|
|
addr: u16,
|
|
|
|
/// The instruction after the breakpoint
|
|
|
|
next: u16,
|
|
|
|
},
|
2023-03-29 23:45:39 -05:00
|
|
|
/// Represents an unimplemented operation
|
2023-03-30 10:46:35 -05:00
|
|
|
#[error("Unrecognized opcode: {word:04x}")]
|
2023-03-29 23:42:41 -05:00
|
|
|
UnimplementedInstruction {
|
2023-03-29 23:45:39 -05:00
|
|
|
/// The offending word
|
2023-03-29 23:42:41 -05:00
|
|
|
word: u16,
|
|
|
|
},
|
2023-03-29 23:45:39 -05:00
|
|
|
/// The region you asked for was not defined
|
I/O: KISS the bus, attach a screen, plug in a controller
Chip-8 has no ROM, nor memory management.
- It's much easier to just use contiguous memory.
- Then we can return references to slices of that memory
- ~3x speed increase
Screen exists now, uses 24-bit framebuffer
- We have a 1-bit framebuffer
- I chose colors that look good to me
Controller exists as well, has 16 buttons
- Mapped "0 123 456 789 ab cdef" to (QWERTY) "X 123 QWE ASD zC 4RFV"
- Other chip-8 interpreters may use a different layout
- This is good enough for now.
- F1-F9 map to control functions
- F1, F2: Dump CPU registers/screen contents
- F3, F4: Toggle disassembly/pause
- F5: Single-step the CPU, pausing after
- F6, F7: Set/Unset breakpoint
- F8, F9: Soft/Hard Reset CPU
2023-03-22 15:03:53 -05:00
|
|
|
#[error("No {region} found on bus")]
|
2023-03-29 23:42:41 -05:00
|
|
|
MissingRegion {
|
2023-03-29 23:45:39 -05:00
|
|
|
/// The offending [Region]
|
2023-03-29 23:42:41 -05:00
|
|
|
region: Region,
|
|
|
|
},
|
2023-03-30 08:27:06 -05:00
|
|
|
/// Tried to fetch [Range] from bus, received nothing
|
2023-03-30 10:46:35 -05:00
|
|
|
#[error("Invalid range {range:04x?} for bus")]
|
2023-03-30 08:27:06 -05:00
|
|
|
InvalidBusRange {
|
|
|
|
/// The offending [Range]
|
|
|
|
range: Range<usize>,
|
|
|
|
},
|
2023-04-01 00:14:15 -05:00
|
|
|
/// Tried to press a key that doesn't exist
|
|
|
|
#[error("Invalid key: {key:X}")]
|
|
|
|
InvalidKey {
|
|
|
|
/// The offending key
|
|
|
|
key: usize,
|
|
|
|
},
|
|
|
|
/// Tried to get/set an out-of-bounds register
|
|
|
|
#[error("Invalid register: v{reg:X}")]
|
|
|
|
InvalidRegister {
|
|
|
|
/// The offending register
|
|
|
|
reg: usize,
|
|
|
|
},
|
2023-04-03 02:01:25 -05:00
|
|
|
/// Tried to convert string into mode, but it did not match.
|
|
|
|
#[error("Invalid mode: {mode}")]
|
|
|
|
InvalidMode {
|
|
|
|
/// The string which failed to become a mode
|
|
|
|
mode: String,
|
|
|
|
},
|
2023-03-29 23:45:39 -05:00
|
|
|
/// Error originated in [std::io]
|
I/O: KISS the bus, attach a screen, plug in a controller
Chip-8 has no ROM, nor memory management.
- It's much easier to just use contiguous memory.
- Then we can return references to slices of that memory
- ~3x speed increase
Screen exists now, uses 24-bit framebuffer
- We have a 1-bit framebuffer
- I chose colors that look good to me
Controller exists as well, has 16 buttons
- Mapped "0 123 456 789 ab cdef" to (QWERTY) "X 123 QWE ASD zC 4RFV"
- Other chip-8 interpreters may use a different layout
- This is good enough for now.
- F1-F9 map to control functions
- F1, F2: Dump CPU registers/screen contents
- F3, F4: Toggle disassembly/pause
- F5: Single-step the CPU, pausing after
- F6, F7: Set/Unset breakpoint
- F8, F9: Soft/Hard Reset CPU
2023-03-22 15:03:53 -05:00
|
|
|
#[error(transparent)]
|
|
|
|
IoError(#[from] std::io::Error),
|
2023-03-30 08:27:06 -05:00
|
|
|
/// Error originated in [std::array::TryFromSliceError]
|
|
|
|
#[error(transparent)]
|
|
|
|
TryFromSliceError(#[from] std::array::TryFromSliceError),
|
2023-04-14 22:20:30 -05:00
|
|
|
#[cfg(feature = "minifb")]
|
2023-03-29 23:45:39 -05:00
|
|
|
/// Error originated in [minifb]
|
I/O: KISS the bus, attach a screen, plug in a controller
Chip-8 has no ROM, nor memory management.
- It's much easier to just use contiguous memory.
- Then we can return references to slices of that memory
- ~3x speed increase
Screen exists now, uses 24-bit framebuffer
- We have a 1-bit framebuffer
- I chose colors that look good to me
Controller exists as well, has 16 buttons
- Mapped "0 123 456 789 ab cdef" to (QWERTY) "X 123 QWE ASD zC 4RFV"
- Other chip-8 interpreters may use a different layout
- This is good enough for now.
- F1-F9 map to control functions
- F1, F2: Dump CPU registers/screen contents
- F3, F4: Toggle disassembly/pause
- F5: Single-step the CPU, pausing after
- F6, F7: Set/Unset breakpoint
- F8, F9: Soft/Hard Reset CPU
2023-03-22 15:03:53 -05:00
|
|
|
#[error(transparent)]
|
2023-03-29 23:42:41 -05:00
|
|
|
MinifbError(#[from] minifb::Error),
|
Initial commit:
Created outline of emulator:
The emulator has a Bus, which attaches a CPU to some Memory (Mapped Devices)
The design isn't particularly efficient, but the interpreter only needs to
run at ~500Hz or so. It's Rust. It can do that.
Instructions yet to be implemented:
Cxbb: "Store a random number, masked by bitmask bb, into vX"
Dxyn: "Draw an 8 by n sprite to the screen at coordinates (x, y)"
Fx0A: "Wait for a key, then set vX to the value of the pressed key"
Fx33: "BCD convert X, storing the results in &I[0..3]"
Thoughts going forward:
- It's probably a good idea to parse instructions out into an enum.
I had this in an earlier design, but it didn't really look that good.
However, I haven't read many other emulators before, so I don't know the
style people generally go for.
- I haven't used a native graphics library before, and my cg class was done
entirely in a web browser. That kinda sucks, honestly. Sure the skill
might transfer well, but, >JS
2023-03-08 06:07:33 -06:00
|
|
|
}
|