Add more audio regs; Add sprite struct
This commit is contained in:
parent
4221ed06ac
commit
8c0ef5529c
@ -34,6 +34,24 @@ const STAT_MODE_OAM_INT: u8 = 1 << 5;
|
||||
const STAT_MODE_VBLANK_INT: u8 = 1 << 4;
|
||||
const STAT_MODE_HBLANK_INT: u8 = 1 << 3;
|
||||
|
||||
// Sprite flags
|
||||
/*
|
||||
Bit7 OBJ-to-BG Priority (0=OBJ Above BG, 1=OBJ Behind BG color 1-3)
|
||||
(Used for both BG and Window. BG color 0 is always behind OBJ)
|
||||
Bit6 Y flip (0=Normal, 1=Vertically mirrored)
|
||||
Bit5 X flip (0=Normal, 1=Horizontally mirrored)
|
||||
Bit4 Palette number **Non CGB Mode Only** (0=OBP0, 1=OBP1)
|
||||
Bit3 Tile VRAM-Bank **CGB Mode Only** (0=Bank 0, 1=Bank 1)
|
||||
Bit2-0 Palette number **CGB Mode Only** (OBP0-7)
|
||||
*/
|
||||
|
||||
const SPRITE_OBC_BG_PRIORITY: u8 = 1 << 7;
|
||||
const SPRITE_Y_FLIP: u8 = 1 << 6;
|
||||
const SPRITE_X_FLIP: u8 = 1 << 5;
|
||||
const SPRITE_PALETTE_NO: u8 = 1 << 4; // NonCGB only
|
||||
const SPRITE_TILE_VRAM_BANK: u8 = 1 << 3; // CGB only
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
enum DisplayMode {
|
||||
ReadOAMMemory,
|
||||
@ -48,6 +66,13 @@ impl Default for DisplayMode {
|
||||
}
|
||||
}
|
||||
|
||||
struct Sprite {
|
||||
x: u8,
|
||||
y: u8,
|
||||
tile: u8,
|
||||
flags: u8,
|
||||
}
|
||||
|
||||
pub struct Display {
|
||||
control: u8,
|
||||
status: u8,
|
||||
@ -369,11 +394,37 @@ impl Display {
|
||||
if self.control & CTRL_BG_SPRITE_SIZE > 0 {
|
||||
println!("Wide sprites not tested!");
|
||||
}
|
||||
|
||||
// Order sprites by priority
|
||||
let mut queue: Vec<Sprite> = Vec::new();
|
||||
for i in 0 .. 39 {
|
||||
let mut y: u8 = self.oam[i * 4 + 0];
|
||||
let mut x: u8 = self.oam[i * 4 + 1];
|
||||
let t_num: u8 = self.oam[i * 4 + 2];
|
||||
let flags: u8 = self.oam[i * 4 + 3];
|
||||
queue.push(Sprite{
|
||||
x: self.oam[i * 4 + 0],
|
||||
y: self.oam[i * 4 + 1],
|
||||
tile: self.oam[i * 4 + 2],
|
||||
flags: self.oam[i * 4 + 3],
|
||||
});
|
||||
}
|
||||
|
||||
// This is the non-CGB priority.
|
||||
// Smaller x coord = higher.
|
||||
use std::cmp;
|
||||
queue.sort_by(|x, y| {
|
||||
if x.x > y.x {
|
||||
cmp::Ordering::Greater
|
||||
} else if x.x < y.x {
|
||||
cmp::Ordering::Less
|
||||
} else {
|
||||
cmp::Ordering::Equal
|
||||
}
|
||||
});
|
||||
queue.reverse();
|
||||
|
||||
for i in 0 .. 39 {
|
||||
let mut y: u8 = queue[i].x;
|
||||
let mut x: u8 = queue[i].y;
|
||||
let t_num: u8 = queue[i].tile;
|
||||
let flags: u8 = queue[i].flags;
|
||||
|
||||
if x == 0 || y == 0 {
|
||||
// This sprite is hidden
|
||||
@ -385,7 +436,11 @@ impl Display {
|
||||
|
||||
// Is this sprite on the current line?
|
||||
if y.wrapping_add(8) >= render_y && y <= render_y {
|
||||
let tile_offset_y: usize = render_y as usize - y as usize;
|
||||
let y_o: u8 = match flags & SPRITE_Y_FLIP == SPRITE_Y_FLIP {
|
||||
true => y ^ 7,
|
||||
false => y
|
||||
};
|
||||
let tile_offset_y: usize = render_y as usize - y_o as usize;
|
||||
let tile_base_addr: usize = 0 + t_num as usize * 16;
|
||||
|
||||
let tile_line_1 = self.vram[tile_base_addr + tile_offset_y * 2];
|
||||
@ -403,12 +458,18 @@ impl Display {
|
||||
let b1: bool;
|
||||
let b2: bool;
|
||||
let mut factor = 0;
|
||||
|
||||
let x_o2: u8 = match flags & SPRITE_X_FLIP == SPRITE_X_FLIP {
|
||||
true => x_o ^ 7,
|
||||
false => x_o,
|
||||
};
|
||||
|
||||
if wide_mode && x_o > 7 {
|
||||
b1 = (tile_line_3 & 1 << (14 - x_o)) > 0;
|
||||
b2 = (tile_line_4 & 1 << (14 - x_o)) > 0;
|
||||
b1 = (tile_line_3 & 1 << (14 - x_o2)) > 0;
|
||||
b2 = (tile_line_4 & 1 << (14 - x_o2)) > 0;
|
||||
} else {
|
||||
b1 = (tile_line_1 & 1 << (7 - x_o)) > 0;
|
||||
b2 = (tile_line_2 & 1 << (7 - x_o)) > 0;
|
||||
b1 = (tile_line_1 & 1 << (7 - x_o2)) > 0;
|
||||
b2 = (tile_line_2 & 1 << (7 - x_o2)) > 0;
|
||||
}
|
||||
|
||||
if b1 {
|
||||
|
||||
@ -42,7 +42,6 @@ impl MBC for MBC3 {
|
||||
let addr = addr - 0xA000;
|
||||
match self.active_ram_bank() {
|
||||
0x00 ... 0x03 => {
|
||||
println!("MBC3: Access RAM [{:02X}] {:04X}", self.ram_bank_no, addr);
|
||||
self.ram[self.active_ram_bank() as usize * 0x2000 + addr as usize]
|
||||
}
|
||||
0x08 ... 0x0C => {
|
||||
@ -89,7 +88,6 @@ impl MBC for MBC3 {
|
||||
let addr = addr - 0xA000;
|
||||
match self.active_ram_bank() {
|
||||
0x00 ... 0x03 => {
|
||||
println!("MBC3: Writing RAM [{:02X}] {:04X} = {:02X}", self.ram_bank_no, addr, val);
|
||||
let active_bank = self.active_ram_bank() as usize;
|
||||
self.ram[active_bank * 0x2000 + addr as usize] = val;
|
||||
}
|
||||
|
||||
17
src/sound.rs
17
src/sound.rs
@ -7,6 +7,11 @@ pub struct Sound {
|
||||
sound_output_terminal_selector: u8,
|
||||
sound_freq_low: u8,
|
||||
sound_freq_high: u8,
|
||||
|
||||
channel2_sound_length: u8,
|
||||
channel2_volume: u8,
|
||||
channel2_freq_lo: u8,
|
||||
channel2_freq_hi: u8,
|
||||
}
|
||||
|
||||
impl Sound {
|
||||
@ -20,6 +25,12 @@ impl Sound {
|
||||
0xFF12 => self.sound_control_1 = val,
|
||||
0xFF13 => self.sound_freq_low = val,
|
||||
0xFF14 => self.sound_freq_high = val,
|
||||
|
||||
0xFF16 => self.channel2_sound_length = val,
|
||||
0xFF17 => self.channel2_volume = val,
|
||||
0xFF18 => self.channel2_freq_lo = val,
|
||||
0xFF19 => self.channel2_freq_hi = val,
|
||||
|
||||
0xFF24 => self.sound_channel_volume_control = val,
|
||||
0xFF25 => self.sound_output_terminal_selector = val,
|
||||
0xFF26 => self.enabled = val,
|
||||
@ -35,6 +46,12 @@ impl Sound {
|
||||
0xFF12 => self.sound_control_1,
|
||||
0xFF13 => self.sound_freq_low,
|
||||
0xFF14 => self.sound_freq_high,
|
||||
|
||||
0xFF16 => self.channel2_sound_length,
|
||||
0xFF17 => self.channel2_volume,
|
||||
0xFF18 => self.channel2_freq_lo,
|
||||
0xFF19 => self.channel2_freq_hi,
|
||||
|
||||
0xFF24 => self.sound_channel_volume_control,
|
||||
0xFF25 => self.sound_output_terminal_selector,
|
||||
0xFF26 => self.enabled,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user