- [NEW] MBC3 implementat

This commit is contained in:
2025-01-30 17:14:09 +01:00
parent 454cce304f
commit f8ce706839
3 changed files with 166 additions and 1 deletions

128
mbc3.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include "mbc3.h"
#include "mem.h"
#include "sm83.h"
#include <stdlib.h>
#include <SDL2/SDL.h>
namespace mbc3
{
#define ROM_BANK_SIZE 0x4000
#define RAM_BANK_SIZE 0x2000
uint8_t *rom;
uint8_t exram[4 * RAM_BANK_SIZE];
uint8_t current_rom_bank = 1;
uint8_t current_ram_bank = 0;
bool ram_enabled = false;
bool rtc_mode = false; // false = ROM banking mode, true = RAM banking mode
uint8_t rtc_reg = 0;
uint8_t rtc_latch = 1;
uint8_t RTC[5] {0,0,0,0,0};
uint8_t RTC_latched[5] {0,0,0,0,0};
void reset()
{
for (int i=0; i<4*RAM_BANK_SIZE; ++i) { exram[i] = 0; }
}
void tick()
{
RTC[0]++;
if (RTC[0]==60) {
RTC[0] = 0;
RTC[1]++;
if (RTC[1]==60) {
RTC[1] = 0;
RTC[2]++;
if (RTC[2]==24) {
if (RTC[3]==0xff) {
RTC[3]=0;
if (RTC[4]&0x01) {
RTC[4] = RTC[4] & 0xfe;
RTC[4] = (RTC[4] & 0x80) ? RTC[4] & 0x7f : RTC[4] | 0x80;
} else {
RTC[4] = RTC[4] | 0x01;
}
} else RTC[3]++;
}
}
}
}
void latchClock()
{
for (int i=0; i<5; ++i) RTC_latched[i] = RTC[i];
}
uint8_t readRom(uint16_t address)
{
if (address < 0x4000) {
// ROM Bank 0
return rom[address];
} else {
// Switchable ROM bank
uint32_t banked_address = (current_rom_bank * ROM_BANK_SIZE) + (address - 0x4000);
return rom[banked_address];
}
}
void writeRom(uint16_t address, uint8_t value)
{
if (address < 0x2000) {
// Enable/disable RAM
ram_enabled = (value & 0x0F) == 0x0A;
} else if (address < 0x4000) {
// Select ROM bank
if (value == 0) value = 1; // Bank 0 is not allowed
current_rom_bank = current_rom_bank = (value & 0x7F);
} else if (address < 0x6000) {
// Select RAM bank or upper bits of ROM bank
if (value<=0x03) {
rtc_mode = false;
current_ram_bank = value & 0x03; // 2 bits for RAM bank
} else if ( (value >= 0x8) && (value <= 0x0c) ) {
rtc_mode = true;
rtc_reg = value-8;
}
} else {
// Select banking mode
if ( (rtc_latch == 0) && (value == 1) ) {
latchClock();
}
rtc_latch = value;
}
}
uint8_t readRam(uint16_t address)
{
if (ram_enabled) {
if (rtc_mode) {
return RTC_latched[rtc_reg];
} else {
uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xa000);
return exram[banked_address];
}
}
return 0xff; // Return open bus value when RAM is disabled
}
void writeRam(uint16_t address, uint8_t value)
{
if (ram_enabled) {
if (rtc_mode) {
RTC[rtc_reg] = RTC_latched[rtc_reg] = value;
} else {
uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xa000);
exram[banked_address] = value;
}
}
}
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size)
{
mbc3::rom = rom;
reset();
}
}