built in bootroms!!
This commit is contained in:
parent
b3b0d94522
commit
e738419d4d
4 changed files with 41 additions and 116 deletions
|
@ -76,29 +76,37 @@ where
|
||||||
RomFile::Raw(data) => Rom::load(data, None, camera.clone()),
|
RomFile::Raw(data) => Rom::load(data, None, camera.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let bootrom_enabled = if options.bootrom.is_some() {
|
let (bootrom_enabled, bootrom, cgb) = if let Some(b) = options.bootrom {
|
||||||
if options.skip_bootrom {
|
let bootrom = match b {
|
||||||
RunBootrom::Skip
|
RomFile::Path(path) => match fs::read(path) {
|
||||||
} else {
|
Ok(data) => data,
|
||||||
RunBootrom::Yes
|
Err(e) => {
|
||||||
}
|
println!("Error reading bootROM: {e}");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RomFile::Raw(data) => data,
|
||||||
|
};
|
||||||
|
let cgb =
|
||||||
|
rom.rom_type == CgbRomType::CgbOnly || options.cgb_mode || bootrom.len() > 256;
|
||||||
|
(
|
||||||
|
if options.skip_bootrom {
|
||||||
|
RunBootrom::Skip
|
||||||
|
} else {
|
||||||
|
RunBootrom::Yes
|
||||||
|
},
|
||||||
|
bootrom,
|
||||||
|
cgb,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
RunBootrom::No
|
let cgb = rom.rom_type == CgbRomType::CgbOnly || options.cgb_mode;
|
||||||
|
let bootrom = if cgb {
|
||||||
|
include_bytes!("../../sameboy-bootroms/cgb_boot.bin").to_vec()
|
||||||
|
} else {
|
||||||
|
include_bytes!("../../sameboy-bootroms/dmg_boot.bin").to_vec()
|
||||||
|
};
|
||||||
|
(RunBootrom::Skip, bootrom, cgb)
|
||||||
};
|
};
|
||||||
let bootrom: Option<Vec<u8>> = options.bootrom.map(|v| match v {
|
|
||||||
RomFile::Path(path) => match fs::read(path) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error reading bootROM: {e}");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RomFile::Raw(data) => data,
|
|
||||||
});
|
|
||||||
|
|
||||||
let cgb = rom.rom_type == CgbRomType::CgbOnly
|
|
||||||
|| options.cgb_mode
|
|
||||||
|| bootrom.as_ref().map_or(false, |v| v.len() > 256);
|
|
||||||
|
|
||||||
options.window.prepare(WIDTH, HEIGHT);
|
options.window.prepare(WIDTH, HEIGHT);
|
||||||
options.window.set_title(format!(
|
options.window.set_title(format!(
|
||||||
|
|
|
@ -208,12 +208,12 @@ where
|
||||||
{
|
{
|
||||||
pub(crate) fn init(
|
pub(crate) fn init(
|
||||||
cgb: bool,
|
cgb: bool,
|
||||||
bootrom: Option<Vec<u8>>,
|
bootrom: Vec<u8>,
|
||||||
rom: Rom<C>,
|
rom: Rom<C>,
|
||||||
output: OutputTargets<ColourFormat, R, C>,
|
output: OutputTargets<ColourFormat, R, C>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bootrom,
|
bootrom: Some(bootrom),
|
||||||
rom,
|
rom,
|
||||||
ram: Wram::new(cgb),
|
ram: Wram::new(cgb),
|
||||||
cpu_ram: [0x0; 128],
|
cpu_ram: [0x0; 128],
|
||||||
|
@ -450,32 +450,6 @@ where
|
||||||
self.joypad.update_pressed_keys(latest_state)
|
self.joypad.update_pressed_keys(latest_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn cpu_ram_init(&mut self) {
|
|
||||||
self.set(0xFF04, 0xAD);
|
|
||||||
// self.set(0xFF10, 0x80);
|
|
||||||
// self.set(0xFF11, 0xBF);
|
|
||||||
// self.set(0xFF12, 0xF3);
|
|
||||||
// self.set(0xFF14, 0xBF);
|
|
||||||
// self.set(0xFF16, 0x3F);
|
|
||||||
// self.set(0xFF19, 0xBF);
|
|
||||||
// self.set(0xFF1A, 0x7F);
|
|
||||||
// self.set(0xFF1B, 0xFF);
|
|
||||||
// self.set(0xFF1C, 0x9F);
|
|
||||||
// self.set(0xFF1E, 0xBF);
|
|
||||||
// self.set(0xFF20, 0xFF);
|
|
||||||
// self.set(0xFF23, 0xBF);
|
|
||||||
// self.set(0xFF24, 0x77);
|
|
||||||
// self.set(0xFF25, 0xF3);
|
|
||||||
// self.set(0xFF26, 0xF1);
|
|
||||||
self.set(0xFF40, 0x91);
|
|
||||||
self.set(0xFF47, 0xFC);
|
|
||||||
self.set(0xFF48, 0xFF);
|
|
||||||
self.set(0xFF49, 0xFF);
|
|
||||||
for i in 0xC000..0xE000 {
|
|
||||||
self.set(i, if rand::random() { 0xFF } else { 0x00 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flush_rom(&mut self) {
|
pub fn flush_rom(&mut self) {
|
||||||
self.rom.flush();
|
self.rom.flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,44 +298,3 @@ fn get_cgb_rom_type(data: u8) -> CgbRomType {
|
||||||
_ => CgbRomType::Dmg,
|
_ => CgbRomType::Dmg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CHECKSUM_TABLE: [u8; 79] = [
|
|
||||||
0x00, 0x88, 0x16, 0x36, 0xD1, 0xDB, 0xF2, 0x3C, 0x8C, 0x92, 0x3D, 0x5C, 0x58, 0xC9, 0x3E, 0x70,
|
|
||||||
0x1D, 0x59, 0x69, 0x19, 0x35, 0xA8, 0x14, 0xAA, 0x75, 0x95, 0x99, 0x34, 0x6F, 0x15, 0xFF, 0x97,
|
|
||||||
0x4B, 0x90, 0x17, 0x10, 0x39, 0xF7, 0xF6, 0xA2, 0x49, 0x4E, 0x43, 0x68, 0xE0, 0x8B, 0xF0, 0xCE,
|
|
||||||
0x0C, 0x29, 0xE8, 0xB7, 0x86, 0x9A, 0x52, 0x01, 0x9D, 0x71, 0x9C, 0xBD, 0x5D, 0x6D, 0x67, 0x3F,
|
|
||||||
0x6B, 0xB3, 0x46, 0x28, 0xA5, 0xC6, 0xD3, 0x27, 0x61, 0x18, 0x66, 0x6A, 0xBF, 0x0D, 0xF4,
|
|
||||||
];
|
|
||||||
|
|
||||||
const TIEBREAKER_TABLE: [u8; 29] = [
|
|
||||||
0x42, 0x45, 0x46, 0x41, 0x41, 0x52, 0x42, 0x45, 0x4B, 0x45, 0x4B, 0x20, 0x52, 0x2D, 0x55, 0x52,
|
|
||||||
0x41, 0x52, 0x20, 0x49, 0x4E, 0x41, 0x49, 0x4C, 0x49, 0x43, 0x45, 0x20, 0x52,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_cgb_compat_palette(data: &[u8]) {
|
|
||||||
if data[0x14B] == 0x01 || (data[0x14B] == 0x33 && data[0x144] == 0x30 && data[0x145] == 0x31) {
|
|
||||||
let checksum = data
|
|
||||||
.iter()
|
|
||||||
.take(0x143)
|
|
||||||
.skip(0x134)
|
|
||||||
.fold(0_u8, |acc, val| acc.wrapping_add(*val));
|
|
||||||
|
|
||||||
let index = CHECKSUM_TABLE
|
|
||||||
.iter()
|
|
||||||
.position(|v| *v == checksum)
|
|
||||||
.unwrap_or(0);
|
|
||||||
if index <= 64 {
|
|
||||||
println!("checksum: {checksum:#X}, index: {index:#X}");
|
|
||||||
} else {
|
|
||||||
let fourth = data[0x137];
|
|
||||||
let tiebreaker = TIEBREAKER_TABLE
|
|
||||||
.iter()
|
|
||||||
.position(|v| *v == fourth)
|
|
||||||
.unwrap_or(0);
|
|
||||||
println!("checksum: {checksum:#X}, index: {index:#X}, fourth: {fourth:#X}, tiebreaker: {tiebreaker:#X}");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ pub(crate) enum Direction {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub(crate) enum RunBootrom {
|
pub(crate) enum RunBootrom {
|
||||||
No,
|
|
||||||
Yes,
|
Yes,
|
||||||
Skip,
|
Skip,
|
||||||
}
|
}
|
||||||
|
@ -82,14 +81,10 @@ where
|
||||||
R: Renderer<ColourFormat>,
|
R: Renderer<ColourFormat>,
|
||||||
C: PocketCamera + Send + 'static,
|
C: PocketCamera + Send + 'static,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(mut memory: Memory<ColourFormat, R, C>, run_bootrom: RunBootrom) -> Self {
|
pub(crate) fn new(memory: Memory<ColourFormat, R, C>, run_bootrom: RunBootrom) -> Self {
|
||||||
let is_running_bootrom = run_bootrom != RunBootrom::No;
|
|
||||||
if !is_running_bootrom {
|
|
||||||
memory.cpu_ram_init();
|
|
||||||
}
|
|
||||||
Self {
|
Self {
|
||||||
memory,
|
memory,
|
||||||
reg: Registers::init(is_running_bootrom),
|
reg: Registers::init(),
|
||||||
last_instruction: 0x0,
|
last_instruction: 0x0,
|
||||||
last_instruction_addr: 0x0,
|
last_instruction_addr: 0x0,
|
||||||
halted: false,
|
halted: false,
|
||||||
|
@ -240,25 +235,14 @@ pub struct Registers {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Registers {
|
impl Registers {
|
||||||
fn init(run_bootrom: bool) -> Self {
|
fn init() -> Self {
|
||||||
if run_bootrom {
|
Self {
|
||||||
Self {
|
af: 0,
|
||||||
af: 0,
|
bc: 0,
|
||||||
bc: 0,
|
de: 0,
|
||||||
de: 0,
|
hl: 0,
|
||||||
hl: 0,
|
sp: 0xFFFE,
|
||||||
sp: 0xFFFE,
|
pc: 0,
|
||||||
pc: 0,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Self {
|
|
||||||
af: 0x01B0,
|
|
||||||
bc: 0x0013,
|
|
||||||
de: 0x00D8,
|
|
||||||
hl: 0x014D,
|
|
||||||
sp: 0xFFFE,
|
|
||||||
pc: 0x0100,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue