mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-27 11:31:33 +00:00
Compare commits
No commits in common. "6ad3f9f29b30e516c39364776c55cc4d2d74e49d" and "886fc3cd4afc3f7d67f83ca620a433def80b326e" have entirely different histories.
6ad3f9f29b
...
886fc3cd4a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
*.log
|
*.log
|
||||||
/ignore
|
|
||||||
|
@ -40,8 +40,7 @@ pub struct Bus {
|
|||||||
|
|
||||||
impl Bus {
|
impl Bus {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let game_rom = match ROM::load_file("ignore/dmg-acid2.gb".to_string()) {
|
let game_rom = match ROM::load_file("roms/cpu_instrs_individual/01-special.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/01-special.gb".to_string()) {
|
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/03-op sp,hl.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/03-op sp,hl.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/04-op r,imm.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/04-op r,imm.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/05-op rp.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/05-op rp.gb".to_string()) {
|
||||||
@ -52,8 +51,7 @@ impl Bus {
|
|||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/10-bit ops.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/10-bit ops.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/11-op a,(hl).gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/11-op a,(hl).gb".to_string()) {
|
||||||
Ok(rom) => rom,
|
Ok(rom) => rom,
|
||||||
// _ => ROM::from_bytes(&[0; 0xFFFF])
|
_ => ROM::from_bytes(&[0; 0xFFFF])
|
||||||
_ => panic!("Could not read ROM"),
|
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
data: [0x00; 0x10000],
|
data: [0x00; 0x10000],
|
||||||
|
@ -23,6 +23,7 @@ impl Emulator {
|
|||||||
self.ppu.draw_background(&self.bus);
|
self.ppu.draw_background(&self.bus);
|
||||||
let ppu_frame = self.ppu.get_rgba_frame(&self.bus);
|
let ppu_frame = self.ppu.get_rgba_frame(&self.bus);
|
||||||
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
|
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
|
||||||
|
let rgba = [0x5e, 0x48, 0xe8, 0xff];
|
||||||
pixel.copy_from_slice(&ppu_frame[i]);
|
pixel.copy_from_slice(&ppu_frame[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
142
src/ppu.rs
142
src/ppu.rs
@ -2,22 +2,19 @@ use crate::utils::{
|
|||||||
BitIndex,
|
BitIndex,
|
||||||
get_bit,
|
get_bit,
|
||||||
set_bit,
|
set_bit,
|
||||||
to_bit_index,
|
|
||||||
};
|
};
|
||||||
use crate::bus::{Bus, AddressRange, BANK_ZERO, VIDEO_RAM};
|
use crate::bus::{Bus, BANK_ZERO, VIDEO_RAM};
|
||||||
use crate::cpu::{Cycles};
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
struct ColorPalette(u8, u8, u8, u8);
|
||||||
enum Pixel {
|
|
||||||
White,
|
struct Tile {
|
||||||
Light,
|
|
||||||
Dark,
|
}
|
||||||
Black,
|
|
||||||
|
struct Sprite {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
struct ColorPalette(u8, u8, u8, u8);
|
|
||||||
|
|
||||||
pub enum LCDControl {
|
pub enum LCDControl {
|
||||||
DisplayEnable,
|
DisplayEnable,
|
||||||
@ -53,8 +50,8 @@ pub const FRAME_BUFFER_LENGTH: u32 = WIDTH * HEIGHT;
|
|||||||
const LCD_CONTROL_ADDRESS: u16 = 0xFF40;
|
const LCD_CONTROL_ADDRESS: u16 = 0xFF40;
|
||||||
const LCD_STATUS_ADDRESS: u16 = 0xFF41;
|
const LCD_STATUS_ADDRESS: u16 = 0xFF41;
|
||||||
|
|
||||||
const SCROLL_Y_ADDRESS: u16 = 0xFF42;
|
const SCROLL_X_ADDRESS: u16 = 0xFF42;
|
||||||
const SCROLL_X_ADDRESS: u16 = 0xFF43;
|
const SCROLL_Y_ADDRESS: u16 = 0xFF43;
|
||||||
const LCD_Y_ADDRESS: u16 = 0xFF44;
|
const LCD_Y_ADDRESS: u16 = 0xFF44;
|
||||||
const LCD_Y_COMPARE_ADDRESS: u16 = 0xFF45;
|
const LCD_Y_COMPARE_ADDRESS: u16 = 0xFF45;
|
||||||
const DMA_ADDRESS: u16 = 0xFF46;
|
const DMA_ADDRESS: u16 = 0xFF46;
|
||||||
@ -63,21 +60,49 @@ const OBJECT_PALETTE_0_ADDRESS: u16 = 0xFF48;
|
|||||||
const OBJECT_PALETTE_1_ADDRESS: u16 = 0xFF49;
|
const OBJECT_PALETTE_1_ADDRESS: u16 = 0xFF49;
|
||||||
const WINDOW_X_ADDRESS: u16 = 0xFF4A;
|
const WINDOW_X_ADDRESS: u16 = 0xFF4A;
|
||||||
const WINDOW_Y_ADDRESS: u16 = 0xFF4B;
|
const WINDOW_Y_ADDRESS: u16 = 0xFF4B;
|
||||||
const TILE_MAP_ADDRESS: u16 = 0x9800;
|
|
||||||
|
pub struct Window {}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_x(bus: &Bus) -> u8 {
|
||||||
|
bus.read(WINDOW_X_ADDRESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_x(bus: &mut Bus, val: u8) {
|
||||||
|
bus.write(WINDOW_X_ADDRESS, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_y(bus: &Bus) -> u8 {
|
||||||
|
bus.read(WINDOW_Y_ADDRESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_y(bus: &mut Bus, val: u8) {
|
||||||
|
bus.write(WINDOW_Y_ADDRESS, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PPU {
|
pub struct PPU {
|
||||||
cycles: Cycles,
|
window: Window,
|
||||||
|
|
||||||
rgba_frame: [[u8; 4]; FRAME_BUFFER_LENGTH as usize],
|
rgba_frame: [[u8; 4]; FRAME_BUFFER_LENGTH as usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PPU {
|
impl PPU {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
cycles: Cycles(0),
|
|
||||||
rgba_frame: [[0, 0, 0xFF, 0]; FRAME_BUFFER_LENGTH as usize],
|
rgba_frame: [[0, 0, 0xFF, 0]; FRAME_BUFFER_LENGTH as usize],
|
||||||
|
window: Window::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_sprite(address: u16) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn get_scroll_x(bus: &Bus) -> u8 {
|
fn get_scroll_x(bus: &Bus) -> u8 {
|
||||||
bus.read(SCROLL_X_ADDRESS)
|
bus.read(SCROLL_X_ADDRESS)
|
||||||
}
|
}
|
||||||
@ -158,67 +183,46 @@ impl PPU {
|
|||||||
bus.write(LCD_STATUS_ADDRESS, byte);
|
bus.write(LCD_STATUS_ADDRESS, byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pixel(two_bit_pixel: u8) -> Pixel {
|
fn get_rgba_pixel(two_bit_pixel: u8) -> [u8; 4] {
|
||||||
match two_bit_pixel {
|
match two_bit_pixel {
|
||||||
0x00 => Pixel::White,
|
0x00 => [255, 255, 255, 255],
|
||||||
0x01 => Pixel::Light,
|
0x01 => [192, 192, 192, 0],
|
||||||
0x10 => Pixel::Dark,
|
0x10 => [128, 128, 128, 0],
|
||||||
0x11 => Pixel::Black,
|
0x11 => [0, 0, 0, 0],
|
||||||
_ => Pixel::Black,
|
_ => [0, 0, 0, 0],
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rgba(pixel: Pixel) -> [u8; 4] {
|
|
||||||
match pixel {
|
|
||||||
Pixel::White => [255, 255, 255, 0],
|
|
||||||
Pixel::Light => [192, 192, 192, 0],
|
|
||||||
Pixel::Dark => [81, 81, 81, 0],
|
|
||||||
Pixel::Black => [0, 0, 0, 0],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_background(&mut self, bus: &Bus) {
|
pub fn draw_background(&mut self, bus: &Bus) {
|
||||||
let mut idx = 0;
|
let mut pointer = VIDEO_RAM.begin();
|
||||||
// let mut tile_line: u16 = 0;
|
let mut pixels_drawn: usize = 0;
|
||||||
let mut lcd_y: u8 = 0;
|
while pixels_drawn < FRAME_BUFFER_LENGTH as usize {
|
||||||
while lcd_y < 144 {
|
let byte1 = bus.read(pointer);
|
||||||
let mut lcd_x: u8 = 0;
|
let byte2 = bus.read(pointer + 1);
|
||||||
while lcd_x < 160 {
|
let pixels = PPU::get_byte_pixels(byte1, byte2);
|
||||||
let y = lcd_y.wrapping_add(PPU::get_scroll_y(bus));
|
self.rgba_frame[pixels_drawn] = PPU::get_rgba_pixel(pixels[0]);
|
||||||
let x = lcd_x.wrapping_add(PPU::get_scroll_x(bus));
|
self.rgba_frame[pixels_drawn + 1] = PPU::get_rgba_pixel(pixels[1]);
|
||||||
let index_x = (x as u16 / 8);
|
self.rgba_frame[pixels_drawn + 2] = PPU::get_rgba_pixel(pixels[2]);
|
||||||
let index_y = (y as u16 / 8) * 32;
|
self.rgba_frame[pixels_drawn + 3] = PPU::get_rgba_pixel(pixels[3]);
|
||||||
let index = index_x + index_y;
|
self.rgba_frame[pixels_drawn + 4] = PPU::get_rgba_pixel(pixels[4]);
|
||||||
let tile_line = (y).rem_euclid(8) * 2;
|
self.rgba_frame[pixels_drawn + 5] = PPU::get_rgba_pixel(pixels[5]);
|
||||||
let index_byte = (bus.read(0x9800 + index as u16) as u16) * 16;
|
self.rgba_frame[pixels_drawn + 6] = PPU::get_rgba_pixel(pixels[6]);
|
||||||
|
self.rgba_frame[pixels_drawn + 7] = PPU::get_rgba_pixel(pixels[7]);
|
||||||
let tile_byte_1 = bus.read(0x8000 + tile_line as u16 + index_byte);
|
pixels_drawn += 8;
|
||||||
let tile_byte_2 = bus.read(0x8000 + tile_line as u16 + index_byte + 1);
|
pointer += 2;
|
||||||
|
|
||||||
let pixels = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
|
||||||
|
|
||||||
for pixel in pixels {
|
|
||||||
self.rgba_frame[idx] = PPU::get_rgba(pixel);
|
|
||||||
idx += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lcd_x += 8;
|
|
||||||
}
|
|
||||||
lcd_y += 1;
|
|
||||||
// tile_line += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_byte_pixels(byte1: u8, byte2: u8) -> [Pixel; 8] {
|
fn get_byte_pixels(byte1: u8, byte2: u8) -> [u8; 8] {
|
||||||
let mut pixels: [Pixel; 8] = [Pixel::White; 8];
|
let mut pixels: [u8; 8] = [0; 8];
|
||||||
pixels[0] = PPU::get_pixel(((get_bit(byte1, BitIndex::I7) as u8) << 1) | (get_bit(byte2, BitIndex::I7) as u8));
|
pixels[0] = ((get_bit(byte1, BitIndex::I7) as u8) << 1) | (get_bit(byte2, BitIndex::I7) as u8);
|
||||||
pixels[1] = PPU::get_pixel(((get_bit(byte1, BitIndex::I6) as u8) << 1) | (get_bit(byte2, BitIndex::I6) as u8));
|
pixels[1] = ((get_bit(byte1, BitIndex::I6) as u8) << 1) | (get_bit(byte2, BitIndex::I6) as u8);
|
||||||
pixels[2] = PPU::get_pixel(((get_bit(byte1, BitIndex::I5) as u8) << 1) | (get_bit(byte2, BitIndex::I5) as u8));
|
pixels[2] = ((get_bit(byte1, BitIndex::I5) as u8) << 1) | (get_bit(byte2, BitIndex::I5) as u8);
|
||||||
pixels[3] = PPU::get_pixel(((get_bit(byte1, BitIndex::I4) as u8) << 1) | (get_bit(byte2, BitIndex::I4) as u8));
|
pixels[3] = ((get_bit(byte1, BitIndex::I4) as u8) << 1) | (get_bit(byte2, BitIndex::I4) as u8);
|
||||||
pixels[4] = PPU::get_pixel(((get_bit(byte1, BitIndex::I3) as u8) << 1) | (get_bit(byte2, BitIndex::I3) as u8));
|
pixels[4] = ((get_bit(byte1, BitIndex::I3) as u8) << 1) | (get_bit(byte2, BitIndex::I3) as u8);
|
||||||
pixels[5] = PPU::get_pixel(((get_bit(byte1, BitIndex::I2) as u8) << 1) | (get_bit(byte2, BitIndex::I2) as u8));
|
pixels[5] = ((get_bit(byte1, BitIndex::I2) as u8) << 1) | (get_bit(byte2, BitIndex::I2) as u8);
|
||||||
pixels[6] = PPU::get_pixel(((get_bit(byte1, BitIndex::I1) as u8) << 1) | (get_bit(byte2, BitIndex::I1) as u8));
|
pixels[6] = ((get_bit(byte1, BitIndex::I1) as u8) << 1) | (get_bit(byte2, BitIndex::I1) as u8);
|
||||||
pixels[7] = PPU::get_pixel(((get_bit(byte1, BitIndex::I0) as u8) << 1) | (get_bit(byte2, BitIndex::I0) as u8));
|
pixels[7] = ((get_bit(byte1, BitIndex::I0) as u8) << 1) | (get_bit(byte2, BitIndex::I0) as u8);
|
||||||
pixels
|
pixels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@ use crate::emulator::Emulator;
|
|||||||
use crate::cpu::{CPU, Cycles};
|
use crate::cpu::{CPU, Cycles};
|
||||||
use crate::ppu::{WIDTH, HEIGHT};
|
use crate::ppu::{WIDTH, HEIGHT};
|
||||||
|
|
||||||
use std::{thread, time};
|
|
||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use pixels::{Error, Pixels, SurfaceTexture};
|
use pixels::{Error, Pixels, SurfaceTexture};
|
||||||
use winit::dpi::LogicalSize;
|
use winit::dpi::LogicalSize;
|
||||||
@ -64,12 +62,10 @@ pub fn start_eventloop() {
|
|||||||
},
|
},
|
||||||
Event::MainEventsCleared => {
|
Event::MainEventsCleared => {
|
||||||
emulator.run(Cycles(70224));
|
emulator.run(Cycles(70224));
|
||||||
emulator.draw(pixels.get_frame());
|
|
||||||
|
|
||||||
thread::sleep(time::Duration::from_millis(14));
|
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
},
|
},
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
|
emulator.draw(pixels.get_frame());
|
||||||
if pixels
|
if pixels
|
||||||
.render()
|
.render()
|
||||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||||
|
14
src/utils.rs
14
src/utils.rs
@ -10,20 +10,6 @@ pub enum BitIndex {
|
|||||||
I7,
|
I7,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_bit_index(index: u8) -> BitIndex {
|
|
||||||
match index {
|
|
||||||
0 => BitIndex::I0,
|
|
||||||
1 => BitIndex::I1,
|
|
||||||
2 => BitIndex::I2,
|
|
||||||
3 => BitIndex::I3,
|
|
||||||
4 => BitIndex::I4,
|
|
||||||
5 => BitIndex::I5,
|
|
||||||
6 => BitIndex::I6,
|
|
||||||
7 => BitIndex::I7,
|
|
||||||
_ => BitIndex::I7,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_bit_index(index: BitIndex) -> u8 {
|
pub fn get_bit_index(index: BitIndex) -> u8 {
|
||||||
match index {
|
match index {
|
||||||
BitIndex::I0 => 0,
|
BitIndex::I0 => 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user