-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
10,037 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "holani" | ||
version = "0.6.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
env_logger = { version = "0.11.5", default-features = false, features = [ "auto-color", "humantime", ] } | ||
log = { version = "0.4", features = ["max_level_trace", "release_max_level_warn"] } | ||
serde = { version = "1.0", features = ["derive"] } | ||
postcard = {version = "1.0", features = ["experimental-derive"] } | ||
bitflags = { version = "2.6", features = ["serde"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,13 @@ | ||
# holani | ||
Atari Lynx emulator | ||
# Holani | ||
A cycle-stepped Atari Lynx emulator. | ||
|
||
The 65C02S cycle-stepped emulation is initially based on the excellent idea and design of [chips](https://github.com/floooh/chips)'s 6502. | ||
|
||
## Holani is a library | ||
You can use [holani-retro](https://github.com/LLeny/holani-retro), a libretro implementation to play official games and homebrews. | ||
|
||
Or for developpers [holani-debug](https://github.com/LLeny/holani-debug), an Atari Lynx debugger built around holani. | ||
|
||
## Holani embeds 6502 binary blobs | ||
* Free Lynx Boot Rom, courtesy of https://bjoern.spruck.net/lynx/ | ||
* BLL uLoader, courtesy of https://github.com/42Bastian/new_bll/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use std::fmt; | ||
|
||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] | ||
pub enum BusStatus { | ||
None, | ||
PeekCart0, | ||
PeekCart1, | ||
PokeCart0, | ||
PokeCart1, | ||
PeekIncCartRipple, | ||
PokeIncCartRipple, | ||
PeekCore, | ||
PokeCore, | ||
Peek, | ||
Poke, | ||
PeekRAM, | ||
PeekDone, | ||
PokeDone, | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub struct Bus { | ||
data: u8, | ||
addr: u16, | ||
status: BusStatus, | ||
request: bool, | ||
grant: bool, | ||
} | ||
|
||
impl Bus { | ||
pub fn new() -> Self { | ||
Self { | ||
data: 0, | ||
addr: 0, | ||
status: BusStatus::None, | ||
request: false, | ||
grant: true, | ||
} | ||
} | ||
|
||
pub fn data(&self) -> u8 { | ||
self.data | ||
} | ||
|
||
pub fn addr(&self) -> u16 { | ||
self.addr | ||
} | ||
|
||
pub fn status(&self) -> BusStatus { | ||
self.status | ||
} | ||
|
||
pub fn request(&self) -> bool { | ||
self.request | ||
} | ||
|
||
pub fn grant(&self) -> bool { | ||
self.grant | ||
} | ||
|
||
pub fn set_data(&mut self, data: u8) { | ||
self.data = data; | ||
} | ||
|
||
pub fn set_addr(&mut self, addr: u16) { | ||
self.addr = addr; | ||
} | ||
|
||
pub fn set_status(&mut self, status: BusStatus) { | ||
self.status = status; | ||
} | ||
|
||
pub fn set_request(&mut self, request: bool) { | ||
self.request = request; | ||
} | ||
|
||
pub fn set_grant(&mut self, grant: bool) { | ||
self.grant = grant; | ||
} | ||
} | ||
|
||
impl Default for Bus { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
impl fmt::Debug for Bus { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{{ addr:{:04x} data:{:04x} status:{:?} request:{:?} grant:{:?} }}", self.addr, self.data, self.status, self.request, self.grant) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use log::trace; | ||
|
||
use super::*; | ||
|
||
pub const _1024KAUDIN_PINS: [u32; 16] = [CART_PIN_A0,CART_PIN_A1,CART_PIN_A2,CART_PIN_A3,CART_PIN_A4,CART_PIN_A5,CART_PIN_A6,CART_PIN_A7,CART_PIN_A8,CART_PIN_A9,CART_PIN_A10,CART_PIN_AUDIN,0,0,0,0]; | ||
pub const _512K_PINS: [u32; 16] = [CART_PIN_A0,CART_PIN_A1,CART_PIN_A2,CART_PIN_A3,CART_PIN_A4,CART_PIN_A5,CART_PIN_A6,CART_PIN_A7,CART_PIN_A8,CART_PIN_A9,CART_PIN_A10,0,0,0,0,0]; | ||
pub const _256K_PINS: [u32; 16] = [CART_PIN_A0,CART_PIN_A1,CART_PIN_A2,CART_PIN_A3,CART_PIN_A4,CART_PIN_A5,CART_PIN_A6,CART_PIN_A7,CART_PIN_A8,CART_PIN_A9,0,0,0,0,0,0]; | ||
pub const _128K_PINS: [u32; 16] = [CART_PIN_A0,CART_PIN_A1,CART_PIN_A2,CART_PIN_A3,CART_PIN_A4,CART_PIN_A5,CART_PIN_A6,CART_PIN_A7,CART_PIN_A8,0,0,0,0,0,0,0]; | ||
pub const BLOCK_PINS: [u32; 8] = [CART_PIN_A12,CART_PIN_A13,CART_PIN_A14,CART_PIN_A15,CART_PIN_A16,CART_PIN_A17,CART_PIN_A18,CART_PIN_A19]; | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub struct CartridgeGeneric { | ||
pins: u32, | ||
banks: Vec<Vec<u8>>, | ||
addr_pins: Vec<u32>, | ||
block_pins: Vec<u32>, | ||
bank_size: u32, | ||
} | ||
|
||
impl CartridgeGeneric { | ||
pub fn new(bank_size: u32, data_pins: &[u32]) -> Self { | ||
Self { | ||
banks: Vec::new(), | ||
pins: 0, | ||
addr_pins: data_pins.to_vec(), | ||
block_pins: BLOCK_PINS.to_vec(), | ||
bank_size, | ||
} | ||
} | ||
|
||
fn block(&self, pins: u32) -> u16 { | ||
read_pins_u16(pins, &self.block_pins) | ||
} | ||
|
||
fn addr(&self, pins: u32) -> u16 { | ||
read_pins_u16(pins, &self.addr_pins) | ||
} | ||
|
||
fn data_address(&self, pins: u32) -> usize { | ||
let block = self.block(pins) as u32; | ||
let addr = self.addr(pins) as u32; | ||
trace!("block:0x{:08X} addr:0x{:08X}", block, addr); | ||
(block * self.bank_size + addr) as usize | ||
} | ||
|
||
fn read(&mut self, pins: u32) -> u32 { | ||
let addr = self.data_address(pins); | ||
let data = self.banks[0][addr]; | ||
trace!("Read 0x{:06x} data:0x{:02x}", addr, data); | ||
write_data_pins(pins, data) | ||
} | ||
|
||
fn write(&mut self, pins: u32) -> u32 { | ||
let addr = self.data_address(pins); | ||
let data = read_pins_u8(pins, DATA_PINS.as_ref()); | ||
self.banks[0][addr] = data; | ||
trace!("Write 0x{:06x} data:0x{:02x}", addr, data); | ||
pins | ||
} | ||
} | ||
|
||
impl CartridgeI for CartridgeGeneric { | ||
fn load(&mut self, file_content: &[u8]){ | ||
self.banks.clear(); | ||
self.banks.push(file_content.to_vec()); | ||
} | ||
|
||
fn set_pins(&mut self, mut pins: u32) { | ||
if self.pins & CART_PIN_CE == 0 && pins & CART_PIN_CE != 0 { | ||
pins = self.read(pins); | ||
} | ||
else if self.pins & CART_PIN_WE == 0 && pins & CART_PIN_WE != 0 { | ||
pins = self.write(pins); | ||
} | ||
|
||
self.pins = pins; | ||
} | ||
|
||
fn pins(&self) -> u32 { | ||
self.pins | ||
} | ||
} |
Oops, something went wrong.