mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
basic HDMA implementation
This commit is contained in:
parent
7925dd75c9
commit
2ca1813939
37
src/bus.rs
37
src/bus.rs
@ -5,6 +5,7 @@ use crate::ram::{RAM, DMGRAM, CGBRAM, WRAM_BANK_SELECT_ADDRESS};
|
|||||||
use crate::ppu::{
|
use crate::ppu::{
|
||||||
PPU,
|
PPU,
|
||||||
DMA_ADDRESS,
|
DMA_ADDRESS,
|
||||||
|
HDMA5_ADDRESS,
|
||||||
};
|
};
|
||||||
use crate::timer::Timer;
|
use crate::timer::Timer;
|
||||||
use crate::joypad::{Joypad, JOYPAD_ADDRESS};
|
use crate::joypad::{Joypad, JOYPAD_ADDRESS};
|
||||||
@ -153,14 +154,11 @@ impl Bus {
|
|||||||
} else if SPRITE_ATTRIBUTE_TABLE.contains(&address) {
|
} else if SPRITE_ATTRIBUTE_TABLE.contains(&address) {
|
||||||
return self.ppu.write_oam(address, data);
|
return self.ppu.write_oam(address, data);
|
||||||
} else if address == DMA_ADDRESS {
|
} else if address == DMA_ADDRESS {
|
||||||
self.data[address as usize] = data;
|
self.ppu.set_register(address, data);
|
||||||
let source = (data as u16) * 0x100;
|
self.dma_transfer(data);
|
||||||
let mut count: u16 = 0;
|
} else if address == HDMA5_ADDRESS {
|
||||||
let oam_addr = SPRITE_ATTRIBUTE_TABLE.min().unwrap();
|
self.ppu.set_register(address, data);
|
||||||
while count < 160 {
|
self.hdma_transfer(data);
|
||||||
self.ppu.write_oam(oam_addr + count, self.read(source + count));
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
} else if PPU::is_io_register(address) {
|
} else if PPU::is_io_register(address) {
|
||||||
self.ppu.set_register(address, data);
|
self.ppu.set_register(address, data);
|
||||||
} else {
|
} else {
|
||||||
@ -173,4 +171,27 @@ impl Bus {
|
|||||||
self.write(address, bytes[0]);
|
self.write(address, bytes[0]);
|
||||||
self.write(address.wrapping_add(1), bytes[1]);
|
self.write(address.wrapping_add(1), bytes[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dma_transfer(&mut self, data: u8) {
|
||||||
|
let source = (data as u16) * 0x100;
|
||||||
|
let mut count: u16 = 0;
|
||||||
|
let oam_addr = SPRITE_ATTRIBUTE_TABLE.min().unwrap();
|
||||||
|
while count < 160 {
|
||||||
|
self.ppu.write_oam(oam_addr + count, self.read(source + count));
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hdma_transfer(&mut self, data: u8) {
|
||||||
|
let source = self.ppu.hdma_source() & 0xFFF0;
|
||||||
|
let destination = (self.ppu.hdma_destination() & 0xFF0) + 0x8000;
|
||||||
|
let length = (((data & 0x7F) as u16) + 1) * 0x10;
|
||||||
|
let mut count: u16 = 0;
|
||||||
|
while count < length {
|
||||||
|
let byte = self.read(source + count);
|
||||||
|
self.ppu.write_vram_external(destination + count, byte);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
self.ppu.set_register(HDMA5_ADDRESS, 0xFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
49
src/ppu.rs
49
src/ppu.rs
@ -29,6 +29,12 @@ pub const WINDOW_Y_ADDRESS: u16 = 0xFF4A;
|
|||||||
pub const WINDOW_X_ADDRESS: u16 = 0xFF4B;
|
pub const WINDOW_X_ADDRESS: u16 = 0xFF4B;
|
||||||
pub const VRAM_BANK_SELECT_ADDRESS: u16 = 0xFF4F;
|
pub const VRAM_BANK_SELECT_ADDRESS: u16 = 0xFF4F;
|
||||||
|
|
||||||
|
pub const HDMA1_ADDRESS: u16 = 0xFF51;
|
||||||
|
pub const HDMA2_ADDRESS: u16 = 0xFF52;
|
||||||
|
pub const HDMA3_ADDRESS: u16 = 0xFF53;
|
||||||
|
pub const HDMA4_ADDRESS: u16 = 0xFF54;
|
||||||
|
pub const HDMA5_ADDRESS: u16 = 0xFF55;
|
||||||
|
|
||||||
pub const BCPS_BGPI_ADDRESS: u16 = 0xFF68;
|
pub const BCPS_BGPI_ADDRESS: u16 = 0xFF68;
|
||||||
pub const BCPD_BGPD_ADDRESS: u16 = 0xFF69;
|
pub const BCPD_BGPD_ADDRESS: u16 = 0xFF69;
|
||||||
pub const OCPS_OBPI_ADDRESS: u16 = 0xFF6A;
|
pub const OCPS_OBPI_ADDRESS: u16 = 0xFF6A;
|
||||||
@ -296,6 +302,9 @@ pub struct PPU {
|
|||||||
obj_cram: [u8; 64],
|
obj_cram: [u8; 64],
|
||||||
oam: [u8; 0xA0],
|
oam: [u8; 0xA0],
|
||||||
vram_bank: u8,
|
vram_bank: u8,
|
||||||
|
hdma_source: u16,
|
||||||
|
hdma_destination: u16,
|
||||||
|
hdma_start: u8,
|
||||||
cgb_mode: bool,
|
cgb_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,6 +338,9 @@ impl PPU {
|
|||||||
obj_cram: [0; 64],
|
obj_cram: [0; 64],
|
||||||
oam: [0; 0xA0],
|
oam: [0; 0xA0],
|
||||||
vram_bank: 0,
|
vram_bank: 0,
|
||||||
|
hdma_source: 0,
|
||||||
|
hdma_destination: 0,
|
||||||
|
hdma_start: 0,
|
||||||
cgb_mode,
|
cgb_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,7 +355,16 @@ impl PPU {
|
|||||||
self.vram_bank | 0xFE
|
self.vram_bank | 0xFE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hdma_source(&self) -> u16 {
|
||||||
|
self.hdma_source
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hdma_destination(&self) -> u16 {
|
||||||
|
self.hdma_destination
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_io_register(address: u16) -> bool {
|
pub fn is_io_register(address: u16) -> bool {
|
||||||
|
(address >= 0xFF51 && address <= 0xFF55) ||
|
||||||
(address >= 0xFF68 && address <= 0xFF6B) ||
|
(address >= 0xFF68 && address <= 0xFF6B) ||
|
||||||
(address >= 0xFF40 && address <= 0xFF4F)
|
(address >= 0xFF40 && address <= 0xFF4F)
|
||||||
}
|
}
|
||||||
@ -369,7 +390,19 @@ impl PPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_register(&self, address: u16) -> u8 {
|
pub fn get_register(&self, address: u16) -> u8 {
|
||||||
if address >= 0xFF68 && address <= 0xFF6B {
|
if address >= 0xFF51 && address <= 0xFF55 {
|
||||||
|
if address == HDMA1_ADDRESS {
|
||||||
|
return self.hdma_source.to_be_bytes()[0];
|
||||||
|
} else if address == HDMA2_ADDRESS {
|
||||||
|
return self.hdma_source.to_be_bytes()[1];
|
||||||
|
} else if address == HDMA3_ADDRESS {
|
||||||
|
return self.hdma_destination.to_be_bytes()[0];
|
||||||
|
} else if address == HDMA4_ADDRESS {
|
||||||
|
return self.hdma_destination.to_be_bytes()[1];
|
||||||
|
} else if address == HDMA5_ADDRESS {
|
||||||
|
return self.hdma_start;
|
||||||
|
}
|
||||||
|
} else if address >= 0xFF68 && address <= 0xFF6B {
|
||||||
return self.cram_registers[(address as usize) - 0xFF68];
|
return self.cram_registers[(address as usize) - 0xFF68];
|
||||||
} else if address == VRAM_BANK_SELECT_ADDRESS {
|
} else if address == VRAM_BANK_SELECT_ADDRESS {
|
||||||
return self.get_vram_bank();
|
return self.get_vram_bank();
|
||||||
@ -382,7 +415,19 @@ impl PPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_register(&mut self, address: u16, data: u8) {
|
pub fn set_register(&mut self, address: u16, data: u8) {
|
||||||
if address >= 0xFF68 && address <= 0xFF6B {
|
if address >= 0xFF51 && address <= 0xFF55 {
|
||||||
|
if address == HDMA1_ADDRESS {
|
||||||
|
self.hdma_source = (self.hdma_source & 0xFF) | ((data as u16) << 8);
|
||||||
|
} else if address == HDMA2_ADDRESS {
|
||||||
|
self.hdma_source = (self.hdma_source & 0xFF00) | (data as u16);
|
||||||
|
} else if address == HDMA3_ADDRESS {
|
||||||
|
self.hdma_destination = (self.hdma_destination & 0xFF) | ((data as u16) << 8);
|
||||||
|
} else if address == HDMA4_ADDRESS {
|
||||||
|
self.hdma_destination = (self.hdma_destination & 0xFF00) | (data as u16);
|
||||||
|
} else if address == HDMA5_ADDRESS {
|
||||||
|
self.hdma_start = data;
|
||||||
|
}
|
||||||
|
} else if address >= 0xFF68 && address <= 0xFF6B {
|
||||||
self.cram_registers[(address as usize) - 0xFF68] = data;
|
self.cram_registers[(address as usize) - 0xFF68] = data;
|
||||||
|
|
||||||
if address == BCPD_BGPD_ADDRESS {
|
if address == BCPD_BGPD_ADDRESS {
|
||||||
|
Loading…
Reference in New Issue
Block a user