- [NEW] Reestructurada tota la gestió de memòria i mapeig de sistemes
This commit is contained in:
224
mbc1.cpp
224
mbc1.cpp
@@ -9,194 +9,74 @@ namespace mbc1
|
||||
#define ROM_BANK_SIZE 0x4000
|
||||
#define RAM_BANK_SIZE 0x2000
|
||||
|
||||
uint8_t bootrom[256];
|
||||
uint8_t *rom;
|
||||
uint8_t vram[8192];
|
||||
uint8_t exram[4 * RAM_BANK_SIZE];
|
||||
uint8_t wram[8192];
|
||||
uint8_t hram[512];
|
||||
|
||||
uint8_t tags[65536];
|
||||
|
||||
uint8_t current_rom_bank = 1;
|
||||
uint8_t current_ram_bank = 0;
|
||||
bool ram_enabled = false;
|
||||
bool banking_mode = false; // false = ROM banking mode, true = RAM banking mode
|
||||
|
||||
uint8_t getKeypad(uint8_t value)
|
||||
{
|
||||
const uint8_t *keys = SDL_GetKeyboardState(NULL);
|
||||
value = value & 0xf0;
|
||||
if (value & 0x10) {
|
||||
if (!keys[SDL_SCANCODE_RETURN]) value = value | 0x8;
|
||||
if (!keys[SDL_SCANCODE_SPACE]) value = value | 0x4;
|
||||
if (!keys[SDL_SCANCODE_Z]) value = value | 0x2;
|
||||
if (!keys[SDL_SCANCODE_X]) value = value | 0x1;
|
||||
} else if (value & 0x20) {
|
||||
if (!keys[SDL_SCANCODE_DOWN]) value = value | 0x8;
|
||||
if (!keys[SDL_SCANCODE_UP]) value = value | 0x4;
|
||||
if (!keys[SDL_SCANCODE_LEFT]) value = value | 0x2;
|
||||
if (!keys[SDL_SCANCODE_RIGHT]) value = value | 0x1;
|
||||
} else {
|
||||
value = value | 0x0f;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t readMem(uint16_t address)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return bootrom[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];
|
||||
}
|
||||
} else if (address < 0xA000) {
|
||||
return vram[address - 0x8000];
|
||||
} else if (address < 0xC000) {
|
||||
if (ram_enabled) {
|
||||
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
|
||||
} else if (address < 0xE000) {
|
||||
return wram[address - 0xC000];
|
||||
} else if (address < 0xFE00) {
|
||||
return wram[address - 0xE000];
|
||||
} else {
|
||||
if (address==0xFF00) {
|
||||
hram[address - 0XFE00] = getKeypad(hram[address - 0XFE00]);
|
||||
}
|
||||
return hram[address - 0XFE00];
|
||||
}
|
||||
}
|
||||
|
||||
void writeMem(uint16_t address, uint8_t value)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
if (address < 0x2000) {
|
||||
// Enable/disable RAM
|
||||
ram_enabled = (value & 0x0F) == 0x0A;
|
||||
} else if (address < 0x4000) {
|
||||
// Select ROM bank
|
||||
value &= 0x1F; // Lower 5 bits are used
|
||||
if (value == 0) value = 1; // Bank 0 is not allowed
|
||||
current_rom_bank = (current_rom_bank & 0x60) | value;
|
||||
} else if (address < 0x6000) {
|
||||
// Select RAM bank or upper bits of ROM bank
|
||||
if (banking_mode) {
|
||||
current_ram_bank = value & 0x03; // 2 bits for RAM bank
|
||||
} else {
|
||||
current_rom_bank = (current_rom_bank & 0x1F) | ((value & 0x03) << 5);
|
||||
}
|
||||
} else {
|
||||
// Select banking mode
|
||||
banking_mode = value & 0x01;
|
||||
}
|
||||
} else if (address < 0xA000) {
|
||||
vram[address - 0x8000] = value;
|
||||
} else if (address < 0xC000) {
|
||||
if (ram_enabled) {
|
||||
uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xA000);
|
||||
exram[banked_address] = value;
|
||||
}
|
||||
} else if (address < 0xE000) {
|
||||
wram[address - 0xC000] = value;
|
||||
} else if (address < 0xFE00) {
|
||||
wram[address - 0xE000] = value;
|
||||
} else {
|
||||
if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room
|
||||
if ( (address==0xFF00) ) { value = value & 0x30; }
|
||||
if ( (address==0xFF04) ) { hram[address-0xFE00] = 0; return; }
|
||||
if ( (address==0xFF0F) ) { hram[address-0xFE00] = value; sm83::processInterrupts(); return; }
|
||||
if ( (address==0xFF46) ) mem::init_dma_transfer(value);
|
||||
hram[address - 0xFE00] = value;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getTag(uint16_t address)
|
||||
{
|
||||
return tags[address];
|
||||
}
|
||||
|
||||
void setTag(uint16_t address, uint8_t value)
|
||||
{
|
||||
tags[address] = value;
|
||||
}
|
||||
|
||||
void saveState(FILE* f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void loadState(FILE *f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t* rawPtr(uint16_t address)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return &bootrom[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];
|
||||
}
|
||||
} else if (address < 0xA000) {
|
||||
return &vram[address - 0x8000];
|
||||
} else if (address < 0xC000) {
|
||||
if (ram_enabled) {
|
||||
uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xA000);
|
||||
return &exram[banked_address];
|
||||
}
|
||||
return nullptr; // Return open bus value when RAM is disabled
|
||||
} else if (address < 0xE000) {
|
||||
return &wram[address - 0xC000];
|
||||
} else if (address < 0xFE00) {
|
||||
return &wram[address - 0xE000];
|
||||
} else {
|
||||
return &hram[address - 0XFE00];
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
FILE *f = fopen("dmg_boot.bin", "rb");
|
||||
if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); }
|
||||
fseek(f, 0, SEEK_END);
|
||||
const int size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(bootrom, size, 1, f);
|
||||
fclose(f);
|
||||
|
||||
for (int i=0; i<8192; ++i) { vram[i] = 0; }
|
||||
for (int i=0; i<4*RAM_BANK_SIZE; ++i) { exram[i] = 0; }
|
||||
for (int i=0; i<8192; ++i) { wram[i] = 0; }
|
||||
for (int i=0; i<512; ++i) { hram[i] = 0; }
|
||||
for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; }
|
||||
}
|
||||
|
||||
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
|
||||
value &= 0x1F; // Lower 5 bits are used
|
||||
if (value == 0) value = 1; // Bank 0 is not allowed
|
||||
current_rom_bank = (current_rom_bank & 0x60) | value;
|
||||
} else if (address < 0x6000) {
|
||||
// Select RAM bank or upper bits of ROM bank
|
||||
if (banking_mode) {
|
||||
current_ram_bank = value & 0x03; // 2 bits for RAM bank
|
||||
} else {
|
||||
current_rom_bank = (current_rom_bank & 0x1F) | ((value & 0x03) << 5);
|
||||
}
|
||||
} else {
|
||||
// Select banking mode
|
||||
banking_mode = value & 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t readRam(uint16_t address)
|
||||
{
|
||||
if (ram_enabled) {
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
mem::readMem = mbc1::readMem;
|
||||
mem::writeMem = mbc1::writeMem;
|
||||
mem::getTag = mbc1::getTag;
|
||||
mem::setTag = mbc1::setTag;
|
||||
mem::saveState = mbc1::saveState;
|
||||
mem::loadState = mbc1::loadState;
|
||||
mem::reset = mbc1::reset;
|
||||
mem::rawPtr = mbc1::rawPtr;
|
||||
|
||||
mbc1::rom = rom;
|
||||
|
||||
reset();
|
||||
}
|
||||
}
|
||||
6
mbc1.h
6
mbc1.h
@@ -4,4 +4,10 @@
|
||||
namespace mbc1
|
||||
{
|
||||
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size);
|
||||
|
||||
void reset();
|
||||
uint8_t readRom(uint16_t address);
|
||||
void writeRom(uint16_t address, uint8_t value);
|
||||
uint8_t readRam(uint16_t address);
|
||||
void writeRam(uint16_t address, uint8_t value);
|
||||
}
|
||||
|
||||
140
mbc_none.cpp
140
mbc_none.cpp
@@ -1,152 +1,22 @@
|
||||
#include "mbc_none.h"
|
||||
#include "mem.h"
|
||||
#include "sm83.h"
|
||||
#include <stdlib.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace mbc_none
|
||||
{
|
||||
uint8_t bootrom[256];
|
||||
uint8_t *rom;
|
||||
uint8_t vram[8192];
|
||||
uint8_t exram[8192];
|
||||
uint8_t wram[8192];
|
||||
uint8_t hram[512];
|
||||
|
||||
uint8_t tags[65536];
|
||||
void reset() { } // nothing to do
|
||||
|
||||
uint8_t getKeypad(uint8_t value)
|
||||
{
|
||||
const uint8_t *keys = SDL_GetKeyboardState(NULL);
|
||||
value = value & 0xf0;
|
||||
if (value & 0x10) {
|
||||
if (!keys[SDL_SCANCODE_RETURN]) value = value | 0x8;
|
||||
if (!keys[SDL_SCANCODE_SPACE]) value = value | 0x4;
|
||||
if (!keys[SDL_SCANCODE_Z]) value = value | 0x2;
|
||||
if (!keys[SDL_SCANCODE_X]) value = value | 0x1;
|
||||
} else if (value & 0x20) {
|
||||
if (!keys[SDL_SCANCODE_DOWN]) value = value | 0x8;
|
||||
if (!keys[SDL_SCANCODE_UP]) value = value | 0x4;
|
||||
if (!keys[SDL_SCANCODE_LEFT]) value = value | 0x2;
|
||||
if (!keys[SDL_SCANCODE_RIGHT]) value = value | 0x1;
|
||||
} else {
|
||||
value = value | 0x0f;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
uint8_t readRom(uint16_t address) { return rom[address]; }
|
||||
|
||||
uint8_t readMem(uint16_t address)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return bootrom[address];
|
||||
return rom[address];
|
||||
} else if (address < 0xA000) {
|
||||
return vram[address - 0x8000];
|
||||
} else if (address < 0xC000) {
|
||||
return exram[address - 0xA000];
|
||||
} else if (address < 0xE000) {
|
||||
return wram[address - 0xC000];
|
||||
} else if (address < 0xFE00) {
|
||||
return wram[address - 0xE000];
|
||||
} else {
|
||||
if (address==0xFF00) {
|
||||
hram[address - 0XFE00] = getKeypad(hram[address - 0XFE00]);
|
||||
}
|
||||
return hram[address - 0XFE00];
|
||||
}
|
||||
}
|
||||
void writeRom(uint16_t address, uint8_t value) { } // do nothing
|
||||
|
||||
void writeMem(uint16_t address, uint8_t value)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
// Read Only Memory, you know...
|
||||
//rom[address] = value;
|
||||
} else if (address < 0xA000) {
|
||||
vram[address - 0x8000] = value;
|
||||
} else if (address < 0xC000) {
|
||||
exram[address - 0xA000] = value;
|
||||
} else if (address < 0xE000) {
|
||||
wram[address - 0xC000] = value;
|
||||
} else if (address < 0xFE00) {
|
||||
wram[address - 0xE000] = value;
|
||||
} else {
|
||||
if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room
|
||||
if ( (address==0xFF00) ) { value = value & 0x30; }
|
||||
if ( (address==0xFF04) ) { hram[address-0xFE00] = 0; return; }
|
||||
if ( (address==0xFF0F) ) { hram[address-0xFE00] = value; sm83::processInterrupts(); return; }
|
||||
if ( (address==0xFF46) ) mem::init_dma_transfer(value);
|
||||
hram[address - 0xFE00] = value;
|
||||
}
|
||||
}
|
||||
uint8_t readRam(uint16_t address) { return 0xff; }
|
||||
|
||||
uint8_t getTag(uint16_t address)
|
||||
{
|
||||
return tags[address];
|
||||
}
|
||||
|
||||
void setTag(uint16_t address, uint8_t value)
|
||||
{
|
||||
tags[address] = value;
|
||||
}
|
||||
|
||||
void saveState(FILE* f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void loadState(FILE *f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t* rawPtr(uint16_t address)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return &bootrom[address];
|
||||
return &rom[address];
|
||||
} else if (address < 0xA000) {
|
||||
return &vram[address - 0x8000];
|
||||
} else if (address < 0xC000) {
|
||||
return &exram[address - 0xA000];
|
||||
} else if (address < 0xE000) {
|
||||
return &wram[address - 0xC000];
|
||||
} else if (address < 0xFE00) {
|
||||
return &wram[address - 0xE000];
|
||||
} else {
|
||||
return &hram[address - 0XFE00];
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
FILE *f = fopen("dmg_boot.bin", "rb");
|
||||
if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); }
|
||||
fseek(f, 0, SEEK_END);
|
||||
const int size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(bootrom, size, 1, f);
|
||||
fclose(f);
|
||||
|
||||
for (int i=0; i<8192; ++i) { vram[i] = 0; }
|
||||
for (int i=0; i<8192; ++i) { exram[i] = 0; }
|
||||
for (int i=0; i<8192; ++i) { wram[i] = 0; }
|
||||
for (int i=0; i<512; ++i) { hram[i] = 0; }
|
||||
for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; }
|
||||
}
|
||||
void writeRam(uint16_t address, uint8_t value) { } // do nothing
|
||||
|
||||
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size)
|
||||
{
|
||||
mem::readMem = mbc_none::readMem;
|
||||
mem::writeMem = mbc_none::writeMem;
|
||||
mem::getTag = mbc_none::getTag;
|
||||
mem::setTag = mbc_none::setTag;
|
||||
mem::saveState = mbc_none::saveState;
|
||||
mem::loadState = mbc_none::loadState;
|
||||
mem::reset = mbc_none::reset;
|
||||
mem::rawPtr = mbc_none::rawPtr;
|
||||
|
||||
mbc_none::rom = rom;
|
||||
|
||||
reset();
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,10 @@
|
||||
namespace mbc_none
|
||||
{
|
||||
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size);
|
||||
|
||||
void reset();
|
||||
uint8_t readRom(uint16_t address);
|
||||
void writeRom(uint16_t address, uint8_t value);
|
||||
uint8_t readRam(uint16_t address);
|
||||
void writeRam(uint16_t address, uint8_t value);
|
||||
}
|
||||
|
||||
170
mem.cpp
170
mem.cpp
@@ -2,21 +2,34 @@
|
||||
#include "sm83.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "mbc_none.h"
|
||||
#include "mbc1.h"
|
||||
|
||||
#define DIV hram[0x104] // 0xff04 - 0xfe00
|
||||
#define TIMA hram[0x105] // 0xff05 - 0xfe00
|
||||
#define TMA hram[0x106] // 0xff06 - 0xfe00
|
||||
#define TAC hram[0x107] // 0xff07 - 0xfe00
|
||||
namespace mem
|
||||
{
|
||||
void (*reset)(void);
|
||||
uint8_t(*readMem)(uint16_t);
|
||||
void (*writeMem)(uint16_t, uint8_t);
|
||||
uint8_t(*getTag)(uint16_t);
|
||||
void (*setTag)(uint16_t, uint8_t);
|
||||
void (*saveState)(FILE*);
|
||||
void (*loadState)(FILE*);
|
||||
uint8_t*(*rawPtr)(uint16_t);
|
||||
|
||||
void (*resetMbc)(void);
|
||||
uint8_t (*readRom)(uint16_t);
|
||||
void (*writeRom)(uint16_t, uint8_t);
|
||||
uint8_t (*readRam)(uint16_t);
|
||||
void (*writeRam)(uint16_t, uint8_t);
|
||||
|
||||
uint8_t bootrom[256];
|
||||
uint8_t *rom;
|
||||
uint8_t vram[8192];
|
||||
uint8_t wram[8192];
|
||||
uint8_t hram[512];
|
||||
|
||||
uint8_t tags[65536];
|
||||
|
||||
char *title = nullptr;
|
||||
uint32_t rom_size = 0;
|
||||
uint32_t ram_size = 0;
|
||||
|
||||
uint16_t dma_address = 0;
|
||||
uint8_t dma_pos = 160;
|
||||
@@ -27,27 +40,142 @@ namespace mem
|
||||
|
||||
void init(uint8_t* rom, const int size)
|
||||
{
|
||||
//if (memory) free(memory);
|
||||
//memory = (uint8_t*)malloc(size);
|
||||
title = (char*)&rom[0x134];
|
||||
uint8_t mapper_type = rom[0x147];
|
||||
uint32_t rom_size = 32768 * (1 << rom[0x148]);
|
||||
rom_size = 32768 * (1 << rom[0x148]);
|
||||
int sizes[] = { 0, 0, 8, 32, 128, 64};
|
||||
uint32_t ram_size = sizes[rom[0x149]] * 1024;
|
||||
ram_size = sizes[rom[0x149]] * 1024;
|
||||
|
||||
switch (mapper_type)
|
||||
{
|
||||
case 0x00:
|
||||
mbc_none::init(rom, rom_size, ram_size);
|
||||
mem::resetMbc = mbc_none::reset;
|
||||
mem::readRom = mbc_none::readRom;
|
||||
mem::writeRom = mbc_none::writeRom;
|
||||
mem::readRam = mbc_none::readRam;
|
||||
mem::writeRam = mbc_none::writeRam;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
mbc1::init(rom, rom_size, ram_size);
|
||||
mem::resetMbc = mbc1::reset;
|
||||
mem::readRom = mbc1::readRom;
|
||||
mem::writeRom = mbc1::writeRom;
|
||||
mem::readRam = mbc1::readRam;
|
||||
mem::writeRam = mbc1::writeRam;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
FILE *f = fopen("dmg_boot.bin", "rb");
|
||||
if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); }
|
||||
fseek(f, 0, SEEK_END);
|
||||
const int size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(bootrom, size, 1, f);
|
||||
fclose(f);
|
||||
|
||||
for (int i=0; i<8192; ++i) { vram[i] = 0; }
|
||||
for (int i=0; i<8192; ++i) { wram[i] = 0; }
|
||||
for (int i=0; i<512; ++i) { hram[i] = 0; }
|
||||
for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; }
|
||||
|
||||
resetMbc();
|
||||
}
|
||||
|
||||
uint8_t getKeypad(uint8_t value)
|
||||
{
|
||||
const uint8_t *keys = SDL_GetKeyboardState(NULL);
|
||||
value = value & 0xf0;
|
||||
if (value & 0x10) {
|
||||
if (!keys[SDL_SCANCODE_RETURN]) value = value | 0x8;
|
||||
if (!keys[SDL_SCANCODE_SPACE]) value = value | 0x4;
|
||||
if (!keys[SDL_SCANCODE_Z]) value = value | 0x2;
|
||||
if (!keys[SDL_SCANCODE_X]) value = value | 0x1;
|
||||
} else if (value & 0x20) {
|
||||
if (!keys[SDL_SCANCODE_DOWN]) value = value | 0x8;
|
||||
if (!keys[SDL_SCANCODE_UP]) value = value | 0x4;
|
||||
if (!keys[SDL_SCANCODE_LEFT]) value = value | 0x2;
|
||||
if (!keys[SDL_SCANCODE_RIGHT]) value = value | 0x1;
|
||||
} else {
|
||||
value = value | 0x0f;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t readMem(uint16_t address)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return bootrom[address];
|
||||
return readRom(address);
|
||||
} else if (address < 0xA000) {
|
||||
return vram[address - 0x8000];
|
||||
} else if (address < 0xC000) {
|
||||
return readRam(address);
|
||||
} else if (address < 0xE000) {
|
||||
return wram[address - 0xC000];
|
||||
} else if (address < 0xFE00) {
|
||||
return wram[address - 0xE000];
|
||||
} else {
|
||||
if (address==0xFF00) {
|
||||
hram[address - 0XFE00] = getKeypad(hram[address - 0XFE00]);
|
||||
}
|
||||
return hram[address - 0XFE00];
|
||||
}
|
||||
}
|
||||
|
||||
void writeMem(uint16_t address, uint8_t value)
|
||||
{
|
||||
if (address < 0x8000) {
|
||||
writeRom(address, value);
|
||||
} else if (address < 0xA000) {
|
||||
vram[address - 0x8000] = value;
|
||||
} else if (address < 0xC000) {
|
||||
writeRam(address, value);
|
||||
} else if (address < 0xE000) {
|
||||
wram[address - 0xC000] = value;
|
||||
} else if (address < 0xFE00) {
|
||||
wram[address - 0xE000] = value;
|
||||
} else {
|
||||
if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room
|
||||
if ( (address==0xFF00) ) { value = value & 0x30; }
|
||||
if ( (address==0xFF04) ) { hram[address-0xFE00] = 0; return; }
|
||||
if ( (address==0xFF0F) ) { hram[address-0xFE00] = value; sm83::processInterrupts(); return; }
|
||||
if ( (address==0xFF46) ) mem::init_dma_transfer(value);
|
||||
hram[address - 0xFE00] = value;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getTag(uint16_t address)
|
||||
{
|
||||
return tags[address];
|
||||
}
|
||||
|
||||
void setTag(uint16_t address, uint8_t value)
|
||||
{
|
||||
tags[address] = value;
|
||||
}
|
||||
|
||||
void saveState(FILE* f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void loadState(FILE* f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t *rawPtr(uint16_t address)
|
||||
{
|
||||
return &hram[address-0xfe00];
|
||||
}
|
||||
|
||||
|
||||
void init_dma_transfer(uint8_t source)
|
||||
{
|
||||
dma_address = source << 8;
|
||||
@@ -62,21 +190,19 @@ namespace mem
|
||||
div_counter += dt;
|
||||
if (div_counter>=256) {
|
||||
div_counter -= 256;
|
||||
uint8_t *div = mem::rawPtr(0xff04);
|
||||
*div = *div + 1;
|
||||
DIV++;
|
||||
}
|
||||
|
||||
// Timer
|
||||
uint8_t *t_regs = mem::rawPtr(0xff05);
|
||||
if (*(t_regs+2)&0x4) { // if bit 3 of mem(0xff07) is 1, timer enabled
|
||||
uint16_t freq = timer_frequencies[*(t_regs+2)&0x03];
|
||||
if (TAC&0x4) { // if bit 3 of mem(0xff07) is 1, timer enabled
|
||||
uint16_t freq = timer_frequencies[TAC&0x03];
|
||||
timer_counter += dt;
|
||||
if (timer_counter>=freq) {
|
||||
timer_counter -= freq;
|
||||
if ((*t_regs)<255)
|
||||
(*t_regs)++;
|
||||
if (TIMA<255)
|
||||
TIMA++;
|
||||
else {
|
||||
*t_regs = *(t_regs+1);
|
||||
TIMA = TMA;
|
||||
sm83::interrupt(INTERRUPT_TIMER);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +214,7 @@ namespace mem
|
||||
dma_dots += dt;
|
||||
while (dma_dots >= 4 && dma_pos<160) {
|
||||
dma_dots -= 4;
|
||||
mem::writeMem(0xfe00|dma_pos, mem::readMem(dma_address|dma_pos));
|
||||
hram[dma_pos] = mem::readMem(dma_address|dma_pos);
|
||||
dma_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
16
mem.h
16
mem.h
@@ -25,18 +25,18 @@ namespace mem
|
||||
#define MBC7 7
|
||||
|
||||
void init(uint8_t* rom, const int size);
|
||||
extern void (*reset)(void);
|
||||
void reset();
|
||||
|
||||
extern uint8_t(*readMem)(uint16_t);
|
||||
extern void (*writeMem)(uint16_t, uint8_t);
|
||||
uint8_t readMem(uint16_t address);
|
||||
void writeMem(uint16_t address, uint8_t value);
|
||||
|
||||
extern uint8_t(*getTag)(uint16_t);
|
||||
extern void (*setTag)(uint16_t, uint8_t);
|
||||
uint8_t getTag(uint16_t address);
|
||||
void setTag(uint16_t address, uint8_t value);
|
||||
|
||||
extern void (*saveState)(FILE*);
|
||||
extern void (*loadState)(FILE*);
|
||||
void saveState(FILE* f);
|
||||
void loadState(FILE* f);
|
||||
|
||||
extern uint8_t*(*rawPtr)(uint16_t);
|
||||
uint8_t *rawPtr(uint16_t address);
|
||||
|
||||
void init_dma_transfer(uint8_t source);
|
||||
void update_mapped(const uint32_t dt);
|
||||
|
||||
6
sm83.cpp
6
sm83.cpp
@@ -592,9 +592,9 @@ namespace sm83
|
||||
void HALT()
|
||||
{
|
||||
if (!halted) {
|
||||
uint8_t *IE = mem::rawPtr(0xffff);
|
||||
uint8_t *IF = mem::rawPtr(0xff0f);
|
||||
if ( (ime==0) && ((*IF & *IE) != 0) ) {
|
||||
const uint8_t IE = mem::readMem(0xffff);
|
||||
const uint8_t IF = mem::readMem(0xff0f);
|
||||
if ( (ime==0) && ((IF & IE) != 0) ) {
|
||||
// [TODO] HALT BUG
|
||||
if (pending_ei==2) rPC--;
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user