- [NEW] Reestructurada tota la gestió de memòria i mapeig de sistemes

This commit is contained in:
2025-01-28 12:57:12 +01:00
parent a64a18d1be
commit a617fec42a
7 changed files with 228 additions and 340 deletions

224
mbc1.cpp
View File

@@ -9,194 +9,74 @@ namespace mbc1
#define ROM_BANK_SIZE 0x4000 #define ROM_BANK_SIZE 0x4000
#define RAM_BANK_SIZE 0x2000 #define RAM_BANK_SIZE 0x2000
uint8_t bootrom[256];
uint8_t *rom; uint8_t *rom;
uint8_t vram[8192];
uint8_t exram[4 * RAM_BANK_SIZE]; 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_rom_bank = 1;
uint8_t current_ram_bank = 0; uint8_t current_ram_bank = 0;
bool ram_enabled = false; bool ram_enabled = false;
bool banking_mode = false; // false = ROM banking mode, true = RAM banking mode 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() 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<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) 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; mbc1::rom = rom;
reset(); reset();
} }
} }

6
mbc1.h
View File

@@ -4,4 +4,10 @@
namespace mbc1 namespace mbc1
{ {
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size); 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);
} }

View File

@@ -1,152 +1,22 @@
#include "mbc_none.h" #include "mbc_none.h"
#include "mem.h"
#include "sm83.h"
#include <stdlib.h>
#include <SDL2/SDL.h>
namespace mbc_none namespace mbc_none
{ {
uint8_t bootrom[256];
uint8_t *rom; 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) uint8_t readRom(uint16_t address) { return rom[address]; }
{
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) void writeRom(uint16_t address, uint8_t value) { } // do nothing
{
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 writeMem(uint16_t address, uint8_t value) uint8_t readRam(uint16_t address) { return 0xff; }
{
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 getTag(uint16_t address) void writeRam(uint16_t address, uint8_t value) { } // do nothing
{
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 init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size) 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; mbc_none::rom = rom;
reset(); reset();
} }
} }

View File

@@ -4,4 +4,10 @@
namespace mbc_none namespace mbc_none
{ {
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size); 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
View File

@@ -2,21 +2,34 @@
#include "sm83.h" #include "sm83.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <SDL2/SDL.h>
#include "mbc_none.h" #include "mbc_none.h"
#include "mbc1.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 namespace mem
{ {
void (*reset)(void); void (*resetMbc)(void);
uint8_t(*readMem)(uint16_t); uint8_t (*readRom)(uint16_t);
void (*writeMem)(uint16_t, uint8_t); void (*writeRom)(uint16_t, uint8_t);
uint8_t(*getTag)(uint16_t); uint8_t (*readRam)(uint16_t);
void (*setTag)(uint16_t, uint8_t); void (*writeRam)(uint16_t, uint8_t);
void (*saveState)(FILE*);
void (*loadState)(FILE*); uint8_t bootrom[256];
uint8_t*(*rawPtr)(uint16_t); uint8_t *rom;
uint8_t vram[8192];
uint8_t wram[8192];
uint8_t hram[512];
uint8_t tags[65536];
char *title = nullptr; char *title = nullptr;
uint32_t rom_size = 0;
uint32_t ram_size = 0;
uint16_t dma_address = 0; uint16_t dma_address = 0;
uint8_t dma_pos = 160; uint8_t dma_pos = 160;
@@ -27,27 +40,142 @@ namespace mem
void init(uint8_t* rom, const int size) void init(uint8_t* rom, const int size)
{ {
//if (memory) free(memory);
//memory = (uint8_t*)malloc(size);
title = (char*)&rom[0x134]; title = (char*)&rom[0x134];
uint8_t mapper_type = rom[0x147]; 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}; 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) switch (mapper_type)
{ {
case 0x00: case 0x00:
mbc_none::init(rom, rom_size, ram_size); 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; break;
case 0x01: case 0x01:
case 0x02: case 0x02:
case 0x03: case 0x03:
mbc1::init(rom, rom_size, ram_size); 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; 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) void init_dma_transfer(uint8_t source)
{ {
dma_address = source << 8; dma_address = source << 8;
@@ -62,21 +190,19 @@ namespace mem
div_counter += dt; div_counter += dt;
if (div_counter>=256) { if (div_counter>=256) {
div_counter -= 256; div_counter -= 256;
uint8_t *div = mem::rawPtr(0xff04); DIV++;
*div = *div + 1;
} }
// Timer // Timer
uint8_t *t_regs = mem::rawPtr(0xff05); if (TAC&0x4) { // if bit 3 of mem(0xff07) is 1, timer enabled
if (*(t_regs+2)&0x4) { // if bit 3 of mem(0xff07) is 1, timer enabled uint16_t freq = timer_frequencies[TAC&0x03];
uint16_t freq = timer_frequencies[*(t_regs+2)&0x03];
timer_counter += dt; timer_counter += dt;
if (timer_counter>=freq) { if (timer_counter>=freq) {
timer_counter -= freq; timer_counter -= freq;
if ((*t_regs)<255) if (TIMA<255)
(*t_regs)++; TIMA++;
else { else {
*t_regs = *(t_regs+1); TIMA = TMA;
sm83::interrupt(INTERRUPT_TIMER); sm83::interrupt(INTERRUPT_TIMER);
} }
} }
@@ -88,7 +214,7 @@ namespace mem
dma_dots += dt; dma_dots += dt;
while (dma_dots >= 4 && dma_pos<160) { while (dma_dots >= 4 && dma_pos<160) {
dma_dots -= 4; 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++; dma_pos++;
} }
} }

16
mem.h
View File

@@ -25,18 +25,18 @@ namespace mem
#define MBC7 7 #define MBC7 7
void init(uint8_t* rom, const int size); void init(uint8_t* rom, const int size);
extern void (*reset)(void); void reset();
extern uint8_t(*readMem)(uint16_t); uint8_t readMem(uint16_t address);
extern void (*writeMem)(uint16_t, uint8_t); void writeMem(uint16_t address, uint8_t value);
extern uint8_t(*getTag)(uint16_t); uint8_t getTag(uint16_t address);
extern void (*setTag)(uint16_t, uint8_t); void setTag(uint16_t address, uint8_t value);
extern void (*saveState)(FILE*); void saveState(FILE* f);
extern void (*loadState)(FILE*); void loadState(FILE* f);
extern uint8_t*(*rawPtr)(uint16_t); uint8_t *rawPtr(uint16_t address);
void init_dma_transfer(uint8_t source); void init_dma_transfer(uint8_t source);
void update_mapped(const uint32_t dt); void update_mapped(const uint32_t dt);

View File

@@ -592,9 +592,9 @@ namespace sm83
void HALT() void HALT()
{ {
if (!halted) { if (!halted) {
uint8_t *IE = mem::rawPtr(0xffff); const uint8_t IE = mem::readMem(0xffff);
uint8_t *IF = mem::rawPtr(0xff0f); const uint8_t IF = mem::readMem(0xff0f);
if ( (ime==0) && ((*IF & *IE) != 0) ) { if ( (ime==0) && ((IF & IE) != 0) ) {
// [TODO] HALT BUG // [TODO] HALT BUG
if (pending_ei==2) rPC--; if (pending_ei==2) rPC--;
return; return;