flashy64_backend/
lib.rs

1extern crate core;
2#[macro_use]
3extern crate lazy_static;
4
5use libftd2xx::{DeviceInfo, Ftdi, FtdiCommon, FtStatus, TimeoutError};
6use log::debug;
7use crate::carts::{Cic, SaveType};
8use crate::carts::sixtyfourdrive::SixtyFourDrive;
9use crate::unfloader::DebugResponse;
10
11pub mod carts;
12pub mod unfloader;
13
14#[derive(Debug, PartialEq)]
15pub enum Error {
16    FtdiStatus(FtStatus),
17    FtdiTimeout(TimeoutError),
18    
19    CommunicationFailed(String),
20    
21    Unsupported,
22}
23impl From<FtStatus> for Error {
24    fn from(value: FtStatus) -> Self {
25        Self::FtdiStatus(value)
26    }
27}
28impl From<TimeoutError> for Error {
29    fn from(value: TimeoutError) -> Self {
30        Self::FtdiTimeout(value)
31    }
32}
33
34pub type Result<T> = std::result::Result<T, Error>;
35
36pub trait Flashcart {
37    fn upload_rom(&mut self, data: &[u8]) -> Result<()>;
38    fn download_rom(&mut self, length: u32) -> Result<Vec<u8>>;
39    
40    fn set_cic(&mut self, cic: Cic) -> Result<()>;
41    fn set_savetype(&mut self, savetype: SaveType) -> Result<()>;
42    
43    fn recv_debug(&mut self) -> Result<DebugResponse>;
44    fn send_debug(&mut self) -> Result<()>;
45    fn info(&mut self) -> Result<DeviceInfo>;
46}
47
48
49pub fn carts() -> Result<Vec<Box<dyn Flashcart>>> {
50    let mut carts = vec![];
51    
52    for info in libftd2xx::list_devices()? {
53        debug!("Device detected: {info:?}");
54        match from_info(&info) {
55            Ok(cart) => carts.push(cart),
56            Err(_) => (),
57        }
58    }
59    
60    Ok(carts)
61}
62
63pub fn from_serial<S: AsRef<str>>(serial: S) -> Result<Box<dyn Flashcart>> {
64    let mut device = Ftdi::with_serial_number(serial.as_ref())?;
65    let info = device.device_info()?;
66    device.close()?;
67    
68    from_info(&info)
69}
70
71pub fn from_info(info: &DeviceInfo) -> Result<Box<dyn Flashcart>> {
72    match (info.vendor_id, info.product_id, info.description.as_str()) {
73        (0x0403, 0x6010, "64drive USB device A") => Ok(Box::new(SixtyFourDrive::new(Ftdi::with_serial_number(&info.serial_number)?)?)),
74        (0x0403, 0x6014, "64drive USB device") => Ok(Box::new(SixtyFourDrive::new(Ftdi::with_serial_number(&info.serial_number)?)?)),
75        (0x0403, 0x6001, "FT245R USB FIFO") => todo!("everdrive"),
76        (0x0403, 0x6014, "SC64") => todo!("summercart64"),
77        
78        _ => Err(Error::Unsupported)
79    }
80}