ref: ad70da3a609ebe96908b8acacadbe13319eaf65c
dir: /sys/src/games/gb/mem.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include "dat.h"
#include "fns.h"
uchar mem[65536];
int rombank, rambank, ramen, battery, ramrom;
extern int savefd;
u8int
memread(u16int p)
{
extern int keys;
if((p & 0xFF80) == 0xFF00)
switch(p){
case 0xFF00:
if((mem[0xFF00] & (1<<5)) == 0)
return (mem[0xFF00] & 0xF0) | ~(keys >> 4);
if((mem[0xFF00] & (1<<6)) == 0)
return (mem[0xFF00] & 0xF0) | ~(keys & 0x0F);
return (mem[0xFF00] & 0xF0) | 0x0F;
}
if(!ramen && ((p & 0xE000) == 0xA000))
return 0xFF;
return mem[p];
}
static void
ramswitch(int state, int bank)
{
if(ramen){
memcpy(ram + 8192 * rambank, mem + 0xA000, 8192);
if(battery && savefd > 0){
seek(savefd, rambank * 8192, 0);
write(savefd, ram + 8192 * rambank, 8192);
}
ramen = 0;
}
rambank = bank;
if(state){
if(bank >= rambanks)
sysfatal("invalid RAM bank %d selected (pc = %.4x)", bank, curpc);
memcpy(mem + 0xA000, ram + 8192 * rambank, 8192);
ramen = 1;
}
}
void
flushram(void)
{
if(ramen)
ramswitch(ramen, rambank);
}
static void
romswitch(int bank)
{
if(bank >= rombanks)
sysfatal("invalid ROM bank %d selected (pc = %.4x)", bank, curpc);
rombank = bank;
memcpy(mem + 0x4000, cart + 0x4000 * bank, 0x4000);
}
void
memwrite(u16int p, u8int v)
{
if(p < 0x8000){
switch(mbc){
case 0:
return;
case 1:
case 2:
switch(p >> 13){
case 0:
if((v & 0x0F) == 0x0A)
ramswitch(1, rambank);
else
ramswitch(0, rambank);
return;
case 1:
v &= 0x1F;
if(v == 0)
v++;
romswitch((rombank & 0xE0) | v);
return;
case 2:
if(ramrom)
ramswitch(ramen, v & 3);
else
romswitch(((v & 3) << 5) | (rombank & 0x1F));
return;
case 3:
ramrom = v;
return;
}
return;
case 3:
switch(p >> 13){
case 0:
if((v & 0x0F) == 0x0A)
ramswitch(1, rambank);
else
ramswitch(0, rambank);
return;
case 1:
v &= 0x7F;
if(v == 0)
v++;
romswitch(v);
return;
case 2:
if(v < 4)
ramswitch(ramen, v);
return;
}
return;
case 5:
switch(p >> 12){
case 0: case 1:
if((v & 0x0F) == 0x0A)
ramswitch(1, rambank);
else
ramswitch(0, rambank);
return;
case 2:
romswitch((rombank & 0x100) | v);
return;
case 3:
romswitch((((int)v & 1) << 8) | (rombank & 0xFF));
return;
case 4:
ramswitch(ramen, v & 15);
return;
}
return;
default:
sysfatal("mbc %d unimplemented", mbc);
}
}
if((p & 0xFF80) == 0xFF00)
switch(p){
case 0xFF04:
v = 0;
break;
case 0xFF07:
timer = (v & 4) != 0;
switch(v & 3){
case 0:
timerfreq = 1024;
break;
case 1:
timerfreq = 16;
break;
case 2:
timerfreq = 64;
break;
default:
timerfreq = 256;
}
break;
case 0xFF26:
v = (v & 0xF0) | (mem[p] & 0x0F);
case 0xFF41:
v &= ~7;
v |= mem[p] & 7;
break;
case 0xFF46:
memcpy(mem + 0xFE00, mem + (((int)v) << 8), 0xA0);
break;
}
mem[p] = v;
}