Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
LLeny committed Oct 2, 2024
1 parent 27820e8 commit ccd5a8d
Show file tree
Hide file tree
Showing 27 changed files with 10,037 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ Cargo.lock
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
#.idea/
11 changes: 11 additions & 0 deletions Cargo.toml
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"] }
15 changes: 13 additions & 2 deletions README.md
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/
94 changes: 94 additions & 0 deletions src/bus.rs
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)
}
}
82 changes: 82 additions & 0 deletions src/cartridge/cartridge_generic.rs
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
}
}
Loading

0 comments on commit ccd5a8d

Please sign in to comment.