Skip to content

Commit ea75fbc

Browse files
committed
Merge branch 'develop'
2 parents 92f46a0 + 9d507aa commit ea75fbc

File tree

13 files changed

+295
-58
lines changed

13 files changed

+295
-58
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ set(GAMEBOYCORE_HEADERS
5858
include/gameboycore/mbc1.h
5959
include/gameboycore/mbc2.h
6060
include/gameboycore/mbc3.h
61+
include/gameboycore/mbc5.h
6162
include/gameboycore/rtc.h
6263
include/gameboycore/cartinfo.h
6364
include/gameboycore/opcodeinfo.h
@@ -79,6 +80,7 @@ set(GAMEBOYCORE
7980
src/core/mbc1.cpp
8081
src/core/mbc2.cpp
8182
src/core/mbc3.cpp
83+
src/core/mbc5.cpp
8284
src/core/alu.cpp
8385
src/core/cartinfo.cpp
8486
src/core/shiftrotate.cpp

include/gameboycore/mbc.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,19 @@ namespace gb
135135
int getIoIndex(uint16_t addr) const;
136136

137137
/**
138+
Get the VRAM offset given the current state of the VBK register
138139
*/
139140
int getVramOffset() const;
140141

142+
/**
143+
Get the internal ram bank offset given the current state of the SVBK register
144+
*/
145+
int getInternalRamOffset() const;
146+
147+
/**
148+
*/
149+
unsigned int kilo(unsigned int n) const;
150+
141151
/**
142152
Load memory
143153
*/
@@ -146,11 +156,13 @@ namespace gb
146156
//! number of switchable rom banks
147157
int num_rom_banks_;
148158
//! number of cartridge ram banks
149-
int num_ram_banks_;
159+
int num_cartridge_ram_banks_;
150160
//! CGB enabled
151161
bool cgb_enabled_;
152-
//!
162+
//! CGB mode has 2 vram banks for character and map data
153163
int vram_banks_;
164+
//! number internal ram banks
165+
int num_internal_ram_banks_;
154166
};
155167
}
156168
}

include/gameboycore/mbc5.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef GAMEBOYCORE_MBC5_H
2+
#define GAMEBOYCORE_MBC5_H
3+
4+
#include "gameboycore/mbc.h"
5+
6+
namespace gb
7+
{
8+
namespace detail
9+
{
10+
class MBC5 : public MBC
11+
{
12+
public:
13+
14+
MBC5(uint8_t* rom, uint32_t size, uint8_t rom_size, uint8_t ram_size, bool cgb_enable);
15+
~MBC5();
16+
17+
void control(uint8_t value, uint16_t addr);
18+
19+
private:
20+
void selectRomBank(uint8_t lo, uint8_t hi);
21+
22+
uint8_t rom_bank_lower_bits_;
23+
uint8_t rom_bank_upper_bit_;
24+
};
25+
}
26+
}
27+
28+
#endif // GAMEBOYCORE_MBC5_H

include/gameboycore/memorymap.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ namespace gb{
139139

140140
DMA_REGISTER = 0xFF46,
141141

142-
VBK = 0xFF4F, ///< VRAM Bank Selection
142+
VBK_REGISTER = 0xFF4F, ///< VRAM Bank Selection
143143

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

156+
SVBK_REGISTER = 0xFF70,
157+
156158
HIGH_RAM_START = 0xFF80,
157159
HIGH_RAM_END = 0xFFFE,
158160

src/core/apu.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ namespace gb
293293
channel_left_enabled_[1] = (value & 0x20) != 0;
294294
channel_left_enabled_[2] = (value & 0x40) != 0;
295295
channel_left_enabled_[3] = (value & 0x80) != 0;
296+
297+
apuWrite(value, addr);
296298
}
297299
else
298300
{
@@ -334,9 +336,10 @@ namespace gb
334336

335337
void clearRegisters()
336338
{
337-
for (auto i = APU_REG_BASE; i < memorymap::WAVE_PATTERN_RAM_START; ++i)
339+
for (auto addr = APU_REG_BASE; addr < memorymap::WAVE_PATTERN_RAM_START; ++addr)
338340
{
339-
apuWrite(0, i);
341+
if (addr == memorymap::NR52_REGISTER) continue;
342+
mmu_->write((uint8_t)0, addr);
340343
}
341344
}
342345

src/core/cpu.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <cstring>
1212
#include <sstream>
1313
#include <iomanip>
14+
#include <iostream>
1415

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

2056+
const int spaces_before_registers = 13;
2057+
std::string padding(spaces_before_registers - std::strlen(str), ' ');
2058+
2059+
// print debug info
2060+
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",
2061+
userdata_addr - 1,
2062+
str,
2063+
padding.c_str(),
2064+
pc_.val,
2065+
af_.hi,
2066+
bc_.hi,
2067+
bc_.lo,
2068+
de_.hi,
2069+
de_.lo,
2070+
hl_.hi,
2071+
hl_.lo,
2072+
sp_.val,
2073+
WORD(mmu_->read(sp_.val + 1), mmu_->read(sp_.val)),
2074+
af_.lo,
2075+
interrupt_flags_,
2076+
interrupt_enable_
2077+
);
2078+
20552079
if (disassembly_callback_)
20562080
disassembly_callback_(ss.str());
20572081

src/core/gpu.cpp

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace gb
1818

1919
static constexpr auto LINE_CYCLES = 456;
2020
static constexpr auto VBLANK_LINE = 144;
21-
static constexpr auto LINE_MAX = 153;
21+
static constexpr auto MAX_LINES = 153;
2222

2323
/* Private Implementation */
2424

@@ -33,6 +33,25 @@ namespace gb
3333
LCD
3434
};
3535

36+
/**
37+
Data needed for HDMA transfer
38+
*/
39+
struct Hdma
40+
{
41+
Hdma() :
42+
transfer_active(false),
43+
source(0),
44+
destination(0),
45+
length(0)
46+
{
47+
}
48+
49+
bool transfer_active;
50+
uint16_t source;
51+
uint16_t destination;
52+
uint16_t length;
53+
};
54+
3655
using CgbPalette = std::array<std::array<gb::Pixel, 4>, 8>;
3756

3857
Impl(MMU::Ptr& mmu) :
@@ -46,8 +65,7 @@ namespace gb
4665
vblank_provider_(*mmu.get(), InterruptProvider::Interrupt::VBLANK),
4766
stat_provider_(*mmu.get(), InterruptProvider::Interrupt::LCDSTAT),
4867
tilemap_(*mmu.get(), palette_),
49-
cgb_enabled_(mmu->cgbEnabled()),
50-
hdma_transfer_start_(false)
68+
cgb_enabled_(mmu->cgbEnabled())
5169
{
5270
mmu->addWriteHandler(memorymap::LCDC_REGISTER, std::bind(&Impl::lcdcWriteHandler, this, std::placeholders::_1, std::placeholders::_2));
5371
mmu->addWriteHandler(memorymap::BGPD, std::bind(&Impl::paletteWriteHandler, this, std::placeholders::_1, std::placeholders::_2));
@@ -67,8 +85,6 @@ namespace gb
6785
// check if the HBLANK period is over
6886
if (hasElapsed(HBLANK_CYCLES))
6987
{
70-
// render the current scan line
71-
renderScanline();
7288
// update the scan line
7389
updateLY();
7490
// check if LY matches LYC
@@ -97,7 +113,12 @@ namespace gb
97113
case Mode::LCD:
98114
if (hasElapsed(LCD_TRANSFER_CYCLES))
99115
{
116+
// render the current scan line
117+
renderScanline();
118+
100119
mode_ = Mode::HBLANK;
120+
// perform an hdma transfer
121+
doHdma();
101122
checkStatInterrupts(ime);
102123
}
103124
break;
@@ -116,6 +137,8 @@ namespace gb
116137
break;
117138
}
118139

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

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

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

158-
const auto background_enabled = IS_SET(lcdc, memorymap::LCDC::BG_DISPLAY_ON) != 0;
159-
const auto window_enabled = IS_SET(lcdc, memorymap::LCDC::WINDOW_ON) != 0;
160-
const auto sprites_enabled = IS_SET(lcdc, memorymap::LCDC::OBJ_ON) != 0;
180+
const auto background_enabled = IS_SET(lcdc_, memorymap::LCDC::BG_DISPLAY_ON) != 0;
181+
const auto window_enabled = IS_SET(lcdc_, memorymap::LCDC::WINDOW_ON) != 0;
182+
const auto sprites_enabled = IS_SET(lcdc_, memorymap::LCDC::OBJ_ON) != 0;
161183

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

182204
auto color_number = tileinfo & 0x03;
183205
auto color_palette = (tileinfo >> 2) & 0x07;
206+
auto priority = (tileinfo >> 5);
184207

185-
color_line[pixel_idx] = color_number;
208+
color_line[pixel_idx] = color_number | (priority << 2);
186209

187210
if (cgb_enabled_)
188211
{
@@ -214,7 +237,7 @@ namespace gb
214237

215238
void updateLY()
216239
{
217-
line_ = (line_ + 1) % LINE_MAX;
240+
line_ = (line_ + 1) % MAX_LINES;
218241
mmu_->write((uint8_t)line_, memorymap::LY_REGISTER);
219242
}
220243

@@ -299,22 +322,56 @@ namespace gb
299322

300323
void hdma5WriteHandler(uint8_t value, uint16_t addr)
301324
{
302-
if (IS_BIT_CLR(value, 7))
303-
{
304-
uint16_t src = WORD(mmu_->read(memorymap::HDMA1), mmu_->read(memorymap::HDMA2));
305-
uint16_t dest = WORD(mmu_->read(memorymap::HDMA3), mmu_->read(memorymap::HDMA4));
306-
uint16_t length = ((value & 0x7F) + 1) * 0x10;
325+
uint16_t src = WORD(mmu_->read(memorymap::HDMA1), mmu_->read(memorymap::HDMA2)) & 0xFFF0;
326+
uint16_t dest = WORD(((mmu_->read(memorymap::HDMA3) & 0x1F) | 0x80), mmu_->read(memorymap::HDMA4)) & 0xFFF0;
327+
uint16_t length = ((value & 0x7F) + 1) * 0x10;
307328

329+
if (IS_BIT_CLR(value, 7) && !hdma_.transfer_active)
330+
{
331+
// perform a general purpose DMA
308332
mmu_->dma(dest, src, length);
309333
}
334+
else if (IS_BIT_CLR(value, 7) && hdma_.transfer_active)
335+
{
336+
// disable an active hdma transfer
337+
hdma_.transfer_active = false;
338+
}
310339
else
311340
{
312-
hdma_transfer_start_ = true;
341+
// initialize an HDMA transfer
342+
hdma_.source = src;
343+
hdma_.destination = dest;
344+
hdma_.length = length;
345+
hdma_.transfer_active = true;
313346
}
314347

315348
hdma5_ = value;
316349
}
317350

351+
void doHdma()
352+
{
353+
if (hdma_.transfer_active)
354+
{
355+
// hdma only works between this range
356+
if (line_ >= 0 && line_ <= 143)
357+
{
358+
// transfer $10 bytes
359+
mmu_->dma(hdma_.destination, hdma_.source, 0x10);
360+
// advance source $10 bytes
361+
hdma_.source += 0x10;
362+
// advance destination $10 bytes
363+
hdma_.destination += 0x10;
364+
// count down the length
365+
hdma_.length -= 0x10;
366+
367+
if (hdma_.length == 0)
368+
{
369+
hdma_.transfer_active = false;
370+
}
371+
}
372+
}
373+
}
374+
318375
void compareLyToLyc(bool ime)
319376
{
320377
auto lyc = mmu_->read(memorymap::LYC_REGISTER);
@@ -359,6 +416,7 @@ namespace gb
359416
uint8_t& lcdc_;
360417
uint8_t& stat_;
361418
uint8_t& hdma5_;
419+
Hdma hdma_;
362420

363421
InterruptProvider vblank_provider_;
364422
InterruptProvider stat_provider_;
@@ -369,7 +427,6 @@ namespace gb
369427
RenderScanlineCallback render_scanline_;
370428

371429
bool cgb_enabled_;
372-
bool hdma_transfer_start_;
373430

374431
CgbPalette cgb_background_palettes_;
375432
CgbPalette cgb_sprite_palette_;

0 commit comments

Comments
 (0)