Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
nnarain committed Aug 30, 2017
2 parents 92f46a0 + 9d507aa commit ea75fbc
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ set(GAMEBOYCORE_HEADERS
include/gameboycore/mbc1.h
include/gameboycore/mbc2.h
include/gameboycore/mbc3.h
include/gameboycore/mbc5.h
include/gameboycore/rtc.h
include/gameboycore/cartinfo.h
include/gameboycore/opcodeinfo.h
Expand All @@ -79,6 +80,7 @@ set(GAMEBOYCORE
src/core/mbc1.cpp
src/core/mbc2.cpp
src/core/mbc3.cpp
src/core/mbc5.cpp
src/core/alu.cpp
src/core/cartinfo.cpp
src/core/shiftrotate.cpp
Expand Down
16 changes: 14 additions & 2 deletions include/gameboycore/mbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,19 @@ namespace gb
int getIoIndex(uint16_t addr) const;

/**
Get the VRAM offset given the current state of the VBK register
*/
int getVramOffset() const;

/**
Get the internal ram bank offset given the current state of the SVBK register
*/
int getInternalRamOffset() const;

/**
*/
unsigned int kilo(unsigned int n) const;

/**
Load memory
*/
Expand All @@ -146,11 +156,13 @@ namespace gb
//! number of switchable rom banks
int num_rom_banks_;
//! number of cartridge ram banks
int num_ram_banks_;
int num_cartridge_ram_banks_;
//! CGB enabled
bool cgb_enabled_;
//!
//! CGB mode has 2 vram banks for character and map data
int vram_banks_;
//! number internal ram banks
int num_internal_ram_banks_;
};
}
}
Expand Down
28 changes: 28 additions & 0 deletions include/gameboycore/mbc5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef GAMEBOYCORE_MBC5_H
#define GAMEBOYCORE_MBC5_H

#include "gameboycore/mbc.h"

namespace gb
{
namespace detail
{
class MBC5 : public MBC
{
public:

MBC5(uint8_t* rom, uint32_t size, uint8_t rom_size, uint8_t ram_size, bool cgb_enable);
~MBC5();

void control(uint8_t value, uint16_t addr);

private:
void selectRomBank(uint8_t lo, uint8_t hi);

uint8_t rom_bank_lower_bits_;
uint8_t rom_bank_upper_bit_;
};
}
}

#endif // GAMEBOYCORE_MBC5_H
4 changes: 3 additions & 1 deletion include/gameboycore/memorymap.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ namespace gb{

DMA_REGISTER = 0xFF46,

VBK = 0xFF4F, ///< VRAM Bank Selection
VBK_REGISTER = 0xFF4F, ///< VRAM Bank Selection

HDMA1 = 0xFF51, ///< New D<A Source High
HDMA2 = 0xFF52, ///< New DMA Source Low
Expand All @@ -153,6 +153,8 @@ namespace gb{
OBPI = 0xFF6A, ///< Object Palette Index
OBPD = 0xFF6B, ///< Object Palette Data

SVBK_REGISTER = 0xFF70,

HIGH_RAM_START = 0xFF80,
HIGH_RAM_END = 0xFFFE,

Expand Down
7 changes: 5 additions & 2 deletions src/core/apu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ namespace gb
channel_left_enabled_[1] = (value & 0x20) != 0;
channel_left_enabled_[2] = (value & 0x40) != 0;
channel_left_enabled_[3] = (value & 0x80) != 0;

apuWrite(value, addr);
}
else
{
Expand Down Expand Up @@ -334,9 +336,10 @@ namespace gb

void clearRegisters()
{
for (auto i = APU_REG_BASE; i < memorymap::WAVE_PATTERN_RAM_START; ++i)
for (auto addr = APU_REG_BASE; addr < memorymap::WAVE_PATTERN_RAM_START; ++addr)
{
apuWrite(0, i);
if (addr == memorymap::NR52_REGISTER) continue;
mmu_->write((uint8_t)0, addr);
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/core/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <cstring>
#include <sstream>
#include <iomanip>
#include <iostream>

#include "bitutil.h"
#include "shiftrotate.h"
Expand Down Expand Up @@ -2052,6 +2053,29 @@ namespace gb
std::stringstream ss;
ss << std::setfill('0') << std::setw(4) << std::uppercase << std::hex << addr << ": " << str;

const int spaces_before_registers = 13;
std::string padding(spaces_before_registers - std::strlen(str), ' ');

// print debug info
std::printf("%04X: %s%s| PC: %04X, A: %02X, BC: %02X%02X, DE: %02X%02X, HL: %02X%02X | SP: %04X -> %04X | F: %02X | IF: %02X, IE: %02X\n",
userdata_addr - 1,
str,
padding.c_str(),
pc_.val,
af_.hi,
bc_.hi,
bc_.lo,
de_.hi,
de_.lo,
hl_.hi,
hl_.lo,
sp_.val,
WORD(mmu_->read(sp_.val + 1), mmu_->read(sp_.val)),
af_.lo,
interrupt_flags_,
interrupt_enable_
);

if (disassembly_callback_)
disassembly_callback_(ss.str());

Expand Down
93 changes: 75 additions & 18 deletions src/core/gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace gb

static constexpr auto LINE_CYCLES = 456;
static constexpr auto VBLANK_LINE = 144;
static constexpr auto LINE_MAX = 153;
static constexpr auto MAX_LINES = 153;

/* Private Implementation */

Expand All @@ -33,6 +33,25 @@ namespace gb
LCD
};

/**
Data needed for HDMA transfer
*/
struct Hdma
{
Hdma() :
transfer_active(false),
source(0),
destination(0),
length(0)
{
}

bool transfer_active;
uint16_t source;
uint16_t destination;
uint16_t length;
};

using CgbPalette = std::array<std::array<gb::Pixel, 4>, 8>;

Impl(MMU::Ptr& mmu) :
Expand All @@ -46,8 +65,7 @@ namespace gb
vblank_provider_(*mmu.get(), InterruptProvider::Interrupt::VBLANK),
stat_provider_(*mmu.get(), InterruptProvider::Interrupt::LCDSTAT),
tilemap_(*mmu.get(), palette_),
cgb_enabled_(mmu->cgbEnabled()),
hdma_transfer_start_(false)
cgb_enabled_(mmu->cgbEnabled())
{
mmu->addWriteHandler(memorymap::LCDC_REGISTER, std::bind(&Impl::lcdcWriteHandler, this, std::placeholders::_1, std::placeholders::_2));
mmu->addWriteHandler(memorymap::BGPD, std::bind(&Impl::paletteWriteHandler, this, std::placeholders::_1, std::placeholders::_2));
Expand All @@ -67,8 +85,6 @@ namespace gb
// check if the HBLANK period is over
if (hasElapsed(HBLANK_CYCLES))
{
// render the current scan line
renderScanline();
// update the scan line
updateLY();
// check if LY matches LYC
Expand Down Expand Up @@ -97,7 +113,12 @@ namespace gb
case Mode::LCD:
if (hasElapsed(LCD_TRANSFER_CYCLES))
{
// render the current scan line
renderScanline();

mode_ = Mode::HBLANK;
// perform an hdma transfer
doHdma();
checkStatInterrupts(ime);
}
break;
Expand All @@ -116,6 +137,8 @@ namespace gb
break;
}

// update LCDC stat mode
stat_ = (stat_ & 0xFC) | (static_cast<uint8_t>(mode_));
}

void setRenderCallback(RenderScanlineCallback callback)
Expand Down Expand Up @@ -153,11 +176,10 @@ namespace gb
auto background_palette = palette_.get(mmu_->read(memorymap::BGP_REGISTER));

// get lcd config
const auto lcdc = mmu_->read(memorymap::LCDC_REGISTER);

const auto background_enabled = IS_SET(lcdc, memorymap::LCDC::BG_DISPLAY_ON) != 0;
const auto window_enabled = IS_SET(lcdc, memorymap::LCDC::WINDOW_ON) != 0;
const auto sprites_enabled = IS_SET(lcdc, memorymap::LCDC::OBJ_ON) != 0;
const auto background_enabled = IS_SET(lcdc_, memorymap::LCDC::BG_DISPLAY_ON) != 0;
const auto window_enabled = IS_SET(lcdc_, memorymap::LCDC::WINDOW_ON) != 0;
const auto sprites_enabled = IS_SET(lcdc_, memorymap::LCDC::OBJ_ON) != 0;

// get background tile line
const auto background = tilemap_.getBackground(line_, cgb_enabled_);
Expand All @@ -181,8 +203,9 @@ namespace gb

auto color_number = tileinfo & 0x03;
auto color_palette = (tileinfo >> 2) & 0x07;
auto priority = (tileinfo >> 5);

color_line[pixel_idx] = color_number;
color_line[pixel_idx] = color_number | (priority << 2);

if (cgb_enabled_)
{
Expand Down Expand Up @@ -214,7 +237,7 @@ namespace gb

void updateLY()
{
line_ = (line_ + 1) % LINE_MAX;
line_ = (line_ + 1) % MAX_LINES;
mmu_->write((uint8_t)line_, memorymap::LY_REGISTER);
}

Expand Down Expand Up @@ -299,22 +322,56 @@ namespace gb

void hdma5WriteHandler(uint8_t value, uint16_t addr)
{
if (IS_BIT_CLR(value, 7))
{
uint16_t src = WORD(mmu_->read(memorymap::HDMA1), mmu_->read(memorymap::HDMA2));
uint16_t dest = WORD(mmu_->read(memorymap::HDMA3), mmu_->read(memorymap::HDMA4));
uint16_t length = ((value & 0x7F) + 1) * 0x10;
uint16_t src = WORD(mmu_->read(memorymap::HDMA1), mmu_->read(memorymap::HDMA2)) & 0xFFF0;
uint16_t dest = WORD(((mmu_->read(memorymap::HDMA3) & 0x1F) | 0x80), mmu_->read(memorymap::HDMA4)) & 0xFFF0;
uint16_t length = ((value & 0x7F) + 1) * 0x10;

if (IS_BIT_CLR(value, 7) && !hdma_.transfer_active)
{
// perform a general purpose DMA
mmu_->dma(dest, src, length);
}
else if (IS_BIT_CLR(value, 7) && hdma_.transfer_active)
{
// disable an active hdma transfer
hdma_.transfer_active = false;
}
else
{
hdma_transfer_start_ = true;
// initialize an HDMA transfer
hdma_.source = src;
hdma_.destination = dest;
hdma_.length = length;
hdma_.transfer_active = true;
}

hdma5_ = value;
}

void doHdma()
{
if (hdma_.transfer_active)
{
// hdma only works between this range
if (line_ >= 0 && line_ <= 143)
{
// transfer $10 bytes
mmu_->dma(hdma_.destination, hdma_.source, 0x10);
// advance source $10 bytes
hdma_.source += 0x10;
// advance destination $10 bytes
hdma_.destination += 0x10;
// count down the length
hdma_.length -= 0x10;

if (hdma_.length == 0)
{
hdma_.transfer_active = false;
}
}
}
}

void compareLyToLyc(bool ime)
{
auto lyc = mmu_->read(memorymap::LYC_REGISTER);
Expand Down Expand Up @@ -359,6 +416,7 @@ namespace gb
uint8_t& lcdc_;
uint8_t& stat_;
uint8_t& hdma5_;
Hdma hdma_;

InterruptProvider vblank_provider_;
InterruptProvider stat_provider_;
Expand All @@ -369,7 +427,6 @@ namespace gb
RenderScanlineCallback render_scanline_;

bool cgb_enabled_;
bool hdma_transfer_start_;

CgbPalette cgb_background_palettes_;
CgbPalette cgb_sprite_palette_;
Expand Down

0 comments on commit ea75fbc

Please sign in to comment.