Skip to content

Commit

Permalink
[core] Refactor DMG compat palettes and add licensee code tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marcellocordeiro committed Jul 21, 2024
1 parent 933b376 commit 28e6033
Show file tree
Hide file tree
Showing 14 changed files with 383 additions and 190 deletions.
174 changes: 125 additions & 49 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ egui = "0.28.1"
enum_dispatch = "0.3.13"
env_logger = "0.11.3"
gb-core = { path = "./core/gb-core" }
image = { version = "0.25.1", default-features = false }
image = { version = "0.25.2", default-features = false }
itertools = "0.13.0"
libretro-rs = "0.1.3"
log = "0.4.22"
Expand All @@ -63,6 +63,6 @@ rfd = "0.14.1"
sdl2 = "0.37.0"
serde = { version = "1.0.204", features = ["derive"] }
serde_json = "1.0.120"
thiserror = "1.0.62"
thiserror = "1.0.63"
wasm-bindgen = "0.2.92"
web-sys = "0.3.69"
18 changes: 18 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,27 @@ cargo +nightly fmt --all && cargo clippy --all-targets
https://github.com/flamegraph-rs/flamegraph

```sh
# cargo
cargo install flamegraph

# Arch
sudo pacman -S cargo-flamegraph

cargo flamegraph --dev -- roms/rom.gb
CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -- roms/rom.gb
```

## Upgrading packages

```sh
# cargo
cargo install cargo-edit

# brew
brew install cargo-edit

# Arch
sudo pacman -S cargo-edit

cargo upgrade -i && cargo update
```
7 changes: 5 additions & 2 deletions core/gb-core/src/cartridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ impl Cartridge {
log::info!("RAM banks: {ram_banks}");
log::info!("CGB flag: {cgb_flag}");
log::info!("SGB flag: {sgb_flag:?}");
log::info!("Old licensee code: {:#04X}", licensee_code.old());
log::info!("New licensee code: {}", licensee_code.new_as_string());
log::info!("Old licensee code: {:#04X}", licensee_code.old_code());
log::info!(
"New licensee code: {}",
licensee_code.new_code().unwrap_or("--")
);

Ok(Self {
rom,
Expand Down
58 changes: 16 additions & 42 deletions core/gb-core/src/cartridge/compatibility_palettes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
// 1. https://gbdev.io/pandocs/Power_Up_Sequence.html#compatibility-palettes
// 2. https://github.com/LIJI32/SameBoy/blob/master/BootROMs/cgb_boot.asm

use self::{
palette_combinations::PALETTE_COMBINATIONS,
palette_id_lookup_table::PALETTE_ID_LOOKUP_TABLE,
title_checksum_lookup_table::TITLE_CHECKSUM_LOOKUP_TABLE,
};
use super::{licensee_code::LicenseeCode, title::Title};
use palette_id::get_palette_id;
use palette_id_index::get_palette_id_index;
use palettes::get_palettes_from_id;

use crate::cartridge::{licensee_code::LicenseeCode, title::Title};

pub struct CompatibilityPalettes {
pub bg0: [u16; 4],
Expand All @@ -16,49 +15,24 @@ pub struct CompatibilityPalettes {
}

impl CompatibilityPalettes {
pub const DEFAULT: Self = PALETTE_COMBINATIONS[0].into_palettes();
pub const DEFAULT: Self = get_palettes_from_id(0);

pub fn from_header_info(licensee_code: &LicenseeCode, title: &Title) -> Self {
match licensee_code.old() {
0x33 => {
if !(licensee_code.new_as_string() == "01"
|| u16::from_le_bytes(*licensee_code.new_as_bytes()) == 0x01)
{
return Self::DEFAULT;
}
}

0x01 => (),

_ => return Self::DEFAULT,
};

let title_checksum = title.checksum();
if !licensee_code.is_nintendo() {
return Self::DEFAULT;
}

let Some(checksum_index) = TITLE_CHECKSUM_LOOKUP_TABLE
.into_iter()
.position(|x| x == title_checksum)
else {
let Some(palette_id_index) = get_palette_id_index(title) else {
return Self::DEFAULT;
};

let palette_id = if checksum_index <= 64 {
PALETTE_ID_LOOKUP_TABLE[checksum_index]
} else {
let fourth_byte = title.as_bytes()[3];
let row = title_row_lookup_table::find_row(checksum_index - 65, fourth_byte);
let index = checksum_index + (14 * row);

PALETTE_ID_LOOKUP_TABLE[index]
};
let palette_id = get_palette_id(palette_id_index);

PALETTE_COMBINATIONS[palette_id].into_palettes()
get_palettes_from_id(palette_id)
}
}

mod palette_combinations;
mod palette_id_lookup_table;
mod palette_lookup_table;
mod palette_lookup_type;
mod title_checksum_lookup_table;
mod title_row_lookup_table;
mod palette;
mod palette_id;
mod palette_id_index;
mod palettes;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// 1. https://gbdev.io/pandocs/Power_Up_Sequence.html#compatibility-palettes
// 2. https://github.com/LIJI32/SameBoy/blob/master/BootROMs/cgb_boot.asm

pub const fn from_index_start(id: usize) -> [u16; 4] {
/// **Fourth step**
///
/// Returns the palette from the id obtained in the previous step.
pub const fn palette_from_id(id: usize) -> [u16; 4] {
[
PALETTE_LOOKUP_TABLE[id],
PALETTE_LOOKUP_TABLE[id + 1],
Expand All @@ -11,7 +14,7 @@ pub const fn from_index_start(id: usize) -> [u16; 4] {
]
}

pub const PALETTE_LOOKUP_TABLE: [u16; 120] = [
const PALETTE_LOOKUP_TABLE: [u16; 120] = [
0x7FFF, 0x32BF, 0x00D0, 0x0000, // 0
0x639F, 0x4279, 0x15B0, 0x04CB, // 1
0x7FFF, 0x6E31, 0x454A, 0x0000, // 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
// 1. https://gbdev.io/pandocs/Power_Up_Sequence.html#compatibility-palettes
// 2. https://github.com/LIJI32/SameBoy/blob/master/BootROMs/cgb_boot.asm

pub const PALETTE_ID_LOOKUP_TABLE: [usize; 94] = [
/// **Second step**
///
/// Used to obtain the palette id given its index from the lookup table.
pub const fn get_palette_id(index: usize) -> usize {
PALETTE_ID[index]
}

/// Indexeded by the index of the title checksum.
const PALETTE_ID: [usize; 94] = [
0, // Default Palette
4, // ALLEY WAY
5, // YAKUMAN
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Taken from
// 1. https://gbdev.io/pandocs/Power_Up_Sequence.html#compatibility-palettes
// 2. https://github.com/LIJI32/SameBoy/blob/master/BootROMs/cgb_boot.asm

use crate::cartridge::title::Title;

/// **First step**
///
/// Used to obtain the index of the palette id.
pub fn get_palette_id_index(title: &Title) -> Option<usize> {
let title_checksum = title.checksum();

let checksum_index = TITLE_CHECKSUM
.into_iter()
.position(|x| x == title_checksum)?;

if checksum_index <= 64 {
Some(checksum_index)
} else {
let fourth_byte = title.as_bytes()[3];
let row = find_title_row(checksum_index - 65, fourth_byte);
let index = checksum_index + (14 * row);

Some(index)
}
}

/// The index will be the index that corresponds to the value of the title checksum in this table.
const TITLE_CHECKSUM: [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, // <-- 64
// Ambiguous. Refer to the fourth byte in the title if the index is >64.
0xB3, 0x46, 0x28, 0xA5, 0xC6, 0xD3, 0x27, 0x61, 0x18, 0x66, 0x6A, 0xBF, 0x0D, 0xF4,
];

/// If the index of the checksum is <= 64, don't use this.
/// If > 64, this will return the index of the palette id lookup table.
fn find_title_row(column: usize, fourth_byte: u8) -> usize {
const TITLE_ROW_LOOKUP_TABLE: [&str; 3] = ["BEFAARBEKEK R-", "URAR INAILICE ", "R"];

if let Some(ch) = TITLE_ROW_LOOKUP_TABLE[0].as_bytes().get(column) {
if *ch == fourth_byte {
return 0;
}
}

if let Some(ch) = TITLE_ROW_LOOKUP_TABLE[1].as_bytes().get(column) {
if *ch == fourth_byte {
return 1;
}
}

if let Some(ch) = TITLE_ROW_LOOKUP_TABLE[2].as_bytes().get(column) {
if *ch == fourth_byte {
return 2;
}
}

0
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,36 @@
// 1. https://gbdev.io/pandocs/Power_Up_Sequence.html#compatibility-palettes
// 2. https://github.com/LIJI32/SameBoy/blob/master/BootROMs/cgb_boot.asm

use super::palette_lookup_type::PaletteLookupKind::{self, Normal, Raw};
use super::palette::palette_from_id;
use crate::cartridge::compatibility_palettes::CompatibilityPalettes;

/// **Third step**
///
/// From the palette id, get each palette for BG0, OBJ1 and OBJ2.
pub const fn get_palettes_from_id(id: usize) -> CompatibilityPalettes {
let (obj0, obj1, bg0) = match PALETTE_COMBINATIONS[id] {
PaletteLookupKind::Normal(obj0, obj1, bg0) => (obj0 * 4, obj1 * 4, bg0 * 4),
PaletteLookupKind::Raw(obj0, obj1, bg0) => (obj0, obj1, bg0),
};

CompatibilityPalettes {
bg0: palette_from_id(bg0),
obj0: palette_from_id(obj0),
obj1: palette_from_id(obj1),
}
}

/// (OBJ0, OBJ1, BG0)
#[derive(Debug, Clone, Copy)]
enum PaletteLookupKind {
Normal(usize, usize, usize),
Raw(usize, usize, usize),
}

use PaletteLookupKind::{Normal, Raw};

#[allow(clippy::erasing_op)]
pub const PALETTE_COMBINATIONS: [PaletteLookupKind; 51] = [
const PALETTE_COMBINATIONS: [PaletteLookupKind; 51] = [
Normal(4, 4, 29),
Normal(18, 18, 18),
Normal(20, 20, 20),
Expand Down

This file was deleted.

This file was deleted.

4 changes: 2 additions & 2 deletions core/gb-core/src/cartridge/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::error::Error;

/// Not the actual start, we're starting at 0 for convenience, as 0..0x100 is the bootrom area.
/// The actual start is at 0x100.
pub const HEADER_START: usize = 0;
pub const HEADER_END: usize = 0x014F;
const HEADER_START: usize = 0;
const HEADER_END: usize = 0x014F;

pub const HEADER_SIZE: usize = HEADER_START + HEADER_END + 1;

Expand Down
Loading

0 comments on commit 28e6033

Please sign in to comment.