mirror of
https://github.com/libretro/fixGB.git
synced 2024-11-23 09:09:40 +00:00
massive audio accuracy improvements, better gbs music compatibility and fixed 8x16 sprite mode
This commit is contained in:
parent
020ba7bb4a
commit
a41e3b497a
174
apu.c
174
apu.c
@ -73,6 +73,17 @@ static const uint16_t noisePeriodNtsc[8] = {
|
||||
8, 16, 32, 48, 64, 80, 96, 112,
|
||||
};
|
||||
|
||||
//wav values from http://gbdev.gg8.se/wiki/articles/Gameboy_sound_hardware#Power_Control
|
||||
static const uint8_t startWavSetDMG[0x10] = {
|
||||
0x84, 0x40, 0x43, 0xAA, 0x2D, 0x78, 0x92, 0x3C,
|
||||
0x60, 0x59, 0x59, 0xB0, 0x34, 0xB8, 0x2E, 0xDA,
|
||||
};
|
||||
|
||||
static const uint8_t startWavSetCGB[0x10] = {
|
||||
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
|
||||
};
|
||||
|
||||
//used externally
|
||||
const uint16_t *noisePeriod;
|
||||
|
||||
@ -85,7 +96,9 @@ void apuInitBufs()
|
||||
{
|
||||
noisePeriod = noisePeriodNtsc;
|
||||
//effective frequency for 60.000Hz Video out
|
||||
apuFrequency = 526680;
|
||||
//apuFrequency = 526680;
|
||||
//effective frequency for original LCD Video out
|
||||
apuFrequency = 524288;
|
||||
double dt = 1.0/((double)apuFrequency);
|
||||
//LP at 22kHz
|
||||
double rc = 1.0/(M_2_PI * 22000.0);
|
||||
@ -107,9 +120,14 @@ void apuDeinitBufs()
|
||||
apuOutBuf = NULL;
|
||||
}
|
||||
|
||||
extern bool allowCgbRegs;
|
||||
void apuInit()
|
||||
{
|
||||
memset(APU_IO_Reg,0,0x50);
|
||||
if(allowCgbRegs) //essentially 50% duty pulse on CGB
|
||||
memcpy(APU_IO_Reg+0x30,startWavSetCGB,0x10);
|
||||
else //relatively random audio pattern on DMG
|
||||
memcpy(APU_IO_Reg+0x30,startWavSetDMG,0x10);
|
||||
memset(apuOutBuf, 0, apuBufSizeBytes);
|
||||
curBufPos = 0;
|
||||
|
||||
@ -143,8 +161,6 @@ void apuInit()
|
||||
extern uint32_t cpu_oam_dma;
|
||||
void apuClockTimers()
|
||||
{
|
||||
if(p1freqCtr)
|
||||
p1freqCtr--;
|
||||
if(p1freqCtr == 0)
|
||||
{
|
||||
if(freq1)
|
||||
@ -153,9 +169,9 @@ void apuClockTimers()
|
||||
if(p1Cycle >= 8)
|
||||
p1Cycle = 0;
|
||||
}
|
||||
if(p1freqCtr)
|
||||
p1freqCtr--;
|
||||
|
||||
if(p2freqCtr)
|
||||
p2freqCtr--;
|
||||
if(p2freqCtr == 0)
|
||||
{
|
||||
if(freq2)
|
||||
@ -164,9 +180,9 @@ void apuClockTimers()
|
||||
if(p2Cycle >= 8)
|
||||
p2Cycle = 0;
|
||||
}
|
||||
if(p2freqCtr)
|
||||
p2freqCtr--;
|
||||
|
||||
if(wavFreqCtr)
|
||||
wavFreqCtr--;
|
||||
if(wavFreqCtr == 0)
|
||||
{
|
||||
wavFreqCtr = (2048-wavFreq)*2;
|
||||
@ -174,9 +190,9 @@ void apuClockTimers()
|
||||
if(wavCycle >= 32)
|
||||
wavCycle = 0;
|
||||
}
|
||||
if(wavFreqCtr)
|
||||
wavFreqCtr--;
|
||||
|
||||
if(noiseFreqCtr)
|
||||
noiseFreqCtr--;
|
||||
if(noiseFreqCtr == 0)
|
||||
{
|
||||
noiseFreqCtr = noiseFreq;
|
||||
@ -185,6 +201,8 @@ void apuClockTimers()
|
||||
noiseShiftReg >>= 1;
|
||||
noiseShiftReg |= cmpRes<<14;
|
||||
}
|
||||
if(noiseFreqCtr)
|
||||
noiseFreqCtr--;
|
||||
}
|
||||
|
||||
static float lastHPOut[2] = { 0, 0 }, lastLPOut[2] = { 0, 0 };
|
||||
@ -225,14 +243,14 @@ bool apuCycle()
|
||||
if(p1enable && p1dacenable && (apuEnableReg & P1_ENABLE))
|
||||
{
|
||||
if(p1seq[p1Cycle] && freq1 > 0 && freq1 <= 0x7FF)
|
||||
lastP1Out[apuCurChan] = p1Out = p1Env.vol;
|
||||
lastP1Out[apuCurChan] = p1Out = p1Env.curVol;
|
||||
else
|
||||
p1Out = 0;
|
||||
}
|
||||
if(p2enable && p2dacenable && (apuEnableReg & P2_ENABLE))
|
||||
{
|
||||
if(p2seq[p2Cycle] && freq2 > 0 && freq2 <= 0x7FF)
|
||||
lastP2Out[apuCurChan] = p2Out = p2Env.vol;
|
||||
lastP2Out[apuCurChan] = p2Out = p2Env.curVol;
|
||||
else
|
||||
p2Out = 0;
|
||||
}
|
||||
@ -252,7 +270,7 @@ bool apuCycle()
|
||||
if(noiseenable && noisedacenable && (apuEnableReg & NOISE_ENABLE))
|
||||
{
|
||||
if((noiseShiftReg&1) == 0 && noiseFreq > 0)
|
||||
lastNoiseOut[apuCurChan] = noiseOut = noiseEnv.vol;
|
||||
lastNoiseOut[apuCurChan] = noiseOut = noiseEnv.curVol;
|
||||
else
|
||||
noiseOut = 0;
|
||||
}
|
||||
@ -279,13 +297,13 @@ void doEnvelopeLogic(envelope_t *env)
|
||||
{
|
||||
if(env->modeadd)
|
||||
{
|
||||
if(env->vol < 15)
|
||||
env->vol++;
|
||||
if(env->curVol < 15)
|
||||
env->curVol++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(env->vol > 0)
|
||||
env->vol--;
|
||||
if(env->curVol > 0)
|
||||
env->curVol--;
|
||||
}
|
||||
}
|
||||
//period 0 is actually period 8!
|
||||
@ -361,10 +379,7 @@ void apuClockA()
|
||||
{
|
||||
p1LengthCtr--;
|
||||
if(p1LengthCtr == 0)
|
||||
{
|
||||
//printf("Len ran out\n");
|
||||
p1enable = false;
|
||||
}
|
||||
}
|
||||
if(p2LengthCtr && !p2haltloop)
|
||||
{
|
||||
@ -427,11 +442,13 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
//printf("APU set %02x %02x\n", reg, val);
|
||||
if(reg == 0x26)
|
||||
{
|
||||
bool wasEnabled = soundEnabled;
|
||||
soundEnabled = (val&0x80)!=0;
|
||||
if(!soundEnabled)
|
||||
{
|
||||
// FULL reset of nearly every reg
|
||||
memset(APU_IO_Reg,0,0x30);
|
||||
// except for the wav buffer
|
||||
memset(APU_IO_Reg+0x40,0,0x10);
|
||||
memset(&p1Env,0,sizeof(envelope_t));
|
||||
memset(&p2Env,0,sizeof(envelope_t));
|
||||
@ -444,8 +461,22 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
p1dacenable = false; p2dacenable = false;
|
||||
wavdacenable = false; noisedacenable = false;
|
||||
freq1 = 0; freq2 = 0; wavFreq = 0; noiseFreq = 0;
|
||||
} //on sound powerup, reset frame sequencer
|
||||
else if(!wasEnabled)
|
||||
{
|
||||
modeCurCtr = 2048;
|
||||
modePos = 0;
|
||||
}
|
||||
}
|
||||
//even if sound off, still update wav buffer
|
||||
else if(reg >= 0x30 && reg < 0x40)
|
||||
{
|
||||
if(wavenable)
|
||||
APU_IO_Reg[0x30+(wavCycle>>1)] = val;
|
||||
else
|
||||
APU_IO_Reg[reg] = val;
|
||||
return;
|
||||
}
|
||||
if(!soundEnabled)
|
||||
return;
|
||||
APU_IO_Reg[reg] = val;
|
||||
@ -466,12 +497,12 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
else if(reg == 0x12)
|
||||
{
|
||||
p1Env.vol = (val>>4)&0xF;
|
||||
p1Env.curVol = p1Env.vol;
|
||||
p1Env.modeadd = (val&8)!=0;
|
||||
p1dacenable = (p1Env.modeadd || p1Env.vol);
|
||||
if(!p1dacenable)
|
||||
p1enable = false;
|
||||
p1Env.period = val&7;
|
||||
p1Env.divider = p1Env.period;
|
||||
}
|
||||
else if(reg == 0x13)
|
||||
{
|
||||
@ -479,15 +510,39 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
}
|
||||
else if(reg == 0x14)
|
||||
{
|
||||
bool p1prevhaltloop = p1haltloop;
|
||||
p1haltloop = ((val&(1<<6)) == 0);
|
||||
freq1 = (freq1&0xFF) | ((val&7)<<8);
|
||||
//if length was previously frozen and we are in
|
||||
//an odd frame sequence, clock length right now
|
||||
if(p1prevhaltloop && !p1haltloop && p1LengthCtr && (modePos&1))
|
||||
{
|
||||
p1LengthCtr--;
|
||||
//disable channel immediately if length
|
||||
//reached 0 from this extra clock
|
||||
if(p1LengthCtr == 0)
|
||||
p1enable = false;
|
||||
}
|
||||
if(val&(1<<7))
|
||||
{
|
||||
if(p1dacenable)
|
||||
p1enable = true;
|
||||
if(p1LengthCtr == 0)
|
||||
{
|
||||
p1LengthCtr = 64;
|
||||
//if length enabled and we are in an odd frame
|
||||
//sequence, subtract one from newly set clock length
|
||||
if(!p1haltloop && (modePos&1))
|
||||
p1LengthCtr--;
|
||||
}
|
||||
//trigger reloads frequency timers
|
||||
p1Cycle = 0;
|
||||
if(freq1)
|
||||
p1freqCtr = (2048-freq1)*4;
|
||||
//trigger resets env volume
|
||||
p1Env.curVol = p1Env.vol;
|
||||
//period 0 is actually period 8!
|
||||
p1Env.divider = (p1Env.period-1)&7;
|
||||
//trigger used to enable/disable sweep
|
||||
if(p1Sweep.period || p1Sweep.shift)
|
||||
p1Sweep.enabled = true;
|
||||
@ -512,12 +567,12 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
else if(reg == 0x17)
|
||||
{
|
||||
p2Env.vol = (val>>4)&0xF;
|
||||
p2Env.curVol = p2Env.vol;
|
||||
p2Env.modeadd = (val&8)!=0;
|
||||
p2dacenable = (p2Env.modeadd || p2Env.vol);
|
||||
if(!p2dacenable)
|
||||
p2enable = false;
|
||||
p2Env.period = val&7;
|
||||
p2Env.divider = p2Env.period;
|
||||
}
|
||||
else if(reg == 0x18)
|
||||
{
|
||||
@ -525,15 +580,39 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
}
|
||||
else if(reg == 0x19)
|
||||
{
|
||||
bool p2prevhaltloop = p2haltloop;
|
||||
p2haltloop = ((val&(1<<6)) == 0);
|
||||
freq2 = (freq2&0xFF) | ((val&7)<<8);
|
||||
//if length was previously frozen and we are in
|
||||
//an odd frame sequence, clock length right now
|
||||
if(p2prevhaltloop && !p2haltloop && p2LengthCtr && (modePos&1))
|
||||
{
|
||||
p2LengthCtr--;
|
||||
//disable channel immediately if length
|
||||
//reached 0 from this extra clock
|
||||
if(p2LengthCtr == 0)
|
||||
p2enable = false;
|
||||
}
|
||||
if(val&(1<<7))
|
||||
{
|
||||
if(p2dacenable)
|
||||
p2enable = true;
|
||||
if(p2LengthCtr == 0)
|
||||
{
|
||||
p2LengthCtr = 64;
|
||||
//if length enabled and we are in an odd frame
|
||||
//sequence, subtract one from newly set clock length
|
||||
if(!p2haltloop && (modePos&1))
|
||||
p2LengthCtr--;
|
||||
}
|
||||
//trigger reloads frequency timers
|
||||
p2Cycle = 0;
|
||||
if(freq2)
|
||||
p2freqCtr = (2048-freq2)*4;
|
||||
//trigger resets env volume
|
||||
p2Env.curVol = p2Env.vol;
|
||||
//period 0 is actually period 8!
|
||||
p2Env.divider = (p2Env.period-1)&7;
|
||||
}
|
||||
//printf("P2 new freq %04x\n", freq2);
|
||||
}
|
||||
@ -571,15 +650,36 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
}
|
||||
else if(reg == 0x1E)
|
||||
{
|
||||
bool wavprevhaltloop = wavhaltloop;
|
||||
wavhaltloop = ((val&(1<<6)) == 0);
|
||||
wavFreq = (wavFreq&0xFF) | ((val&7)<<8);
|
||||
//if length was previously frozen and we are in
|
||||
//an odd frame sequence, clock length right now
|
||||
if(wavprevhaltloop && !wavhaltloop && wavLengthCtr && (modePos&1))
|
||||
{
|
||||
wavLengthCtr--;
|
||||
//disable channel immediately if length
|
||||
//reached 0 from this extra clock
|
||||
if(wavLengthCtr == 0)
|
||||
wavenable = false;
|
||||
}
|
||||
if(val&(1<<7))
|
||||
{
|
||||
if(wavdacenable)
|
||||
wavenable = true;
|
||||
if(wavLengthCtr == 0)
|
||||
{
|
||||
wavLengthCtr = 256;
|
||||
//if length enabled and we are in an odd frame
|
||||
//sequence, subtract one from newly set clock length
|
||||
if(!wavhaltloop && (modePos&1))
|
||||
wavLengthCtr--;
|
||||
}
|
||||
//trigger reloads frequency timers
|
||||
wavCycle = 0;
|
||||
//not sure why +4 needed to sync initally,
|
||||
//probably because of sample buffer byte
|
||||
wavFreqCtr = ((2048-wavFreq)*2)+4;
|
||||
}
|
||||
//printf("wav new freq %04x\n", wavFreq);
|
||||
}
|
||||
@ -590,12 +690,12 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
else if(reg == 0x21)
|
||||
{
|
||||
noiseEnv.vol = (val>>4)&0xF;
|
||||
noiseEnv.curVol = noiseEnv.vol;
|
||||
noiseEnv.modeadd = (val&8)!=0;
|
||||
noisedacenable = (noiseEnv.modeadd || noiseEnv.vol);
|
||||
if(!noisedacenable)
|
||||
noiseenable = false;
|
||||
noiseEnv.period=val&7;
|
||||
noiseEnv.divider = noiseEnv.period;
|
||||
}
|
||||
else if(reg == 0x22)
|
||||
{
|
||||
@ -607,13 +707,36 @@ void apuSet8(uint8_t reg, uint8_t val)
|
||||
}
|
||||
else if(reg == 0x23)
|
||||
{
|
||||
bool prevnoisehaltloop = noisehaltloop;
|
||||
noisehaltloop = ((val&(1<<6)) == 0);
|
||||
//if length was previously frozen and we are in
|
||||
//an odd frame sequence, clock length right now
|
||||
if(prevnoisehaltloop && !noisehaltloop && noiseLengthCtr && (modePos&1))
|
||||
{
|
||||
noiseLengthCtr--;
|
||||
//disable channel immediately if length
|
||||
//reached 0 from this extra clock
|
||||
if(noiseLengthCtr == 0)
|
||||
noiseenable = false;
|
||||
}
|
||||
if(val&(1<<7))
|
||||
{
|
||||
if(noisedacenable)
|
||||
noiseenable = true;
|
||||
if(noiseLengthCtr == 0)
|
||||
{
|
||||
noiseLengthCtr = 64;
|
||||
//if length enabled and we are in an odd frame
|
||||
//sequence, subtract one from newly set clock length
|
||||
if(!noisehaltloop && (modePos&1))
|
||||
noiseLengthCtr--;
|
||||
}
|
||||
//trigger reloads frequency timers
|
||||
noiseFreqCtr = noiseFreq;
|
||||
//trigger resets env volume
|
||||
noiseEnv.curVol = noiseEnv.vol;
|
||||
//period 0 is actually period 8!
|
||||
noiseEnv.divider = (noiseEnv.period-1)&7;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -638,6 +761,13 @@ uint8_t apuGet8(uint8_t reg)
|
||||
uint8_t val;
|
||||
if(reg >= 0x10 && reg < 0x30)
|
||||
val = APU_IO_Reg[reg]|apuReadMask[reg-0x10];
|
||||
else if(reg >= 0x30 && reg < 0x40)
|
||||
{
|
||||
if(wavenable)
|
||||
val = APU_IO_Reg[0x30+(wavCycle>>1)];
|
||||
else
|
||||
val = APU_IO_Reg[reg];
|
||||
}
|
||||
else
|
||||
val = APU_IO_Reg[reg];
|
||||
//printf("APU get %02x %02x\n", reg, val);
|
||||
|
1
apu.h
1
apu.h
@ -26,6 +26,7 @@ void apuLenCycle();
|
||||
typedef struct _envelope_t {
|
||||
bool modeadd;
|
||||
uint8_t vol;
|
||||
uint8_t curVol;
|
||||
uint8_t period;
|
||||
uint8_t divider;
|
||||
} envelope_t;
|
||||
|
40
cpu.c
40
cpu.c
@ -35,6 +35,10 @@ void cpuSetupActionArr();
|
||||
|
||||
static uint16_t sp, pc, cpuTmp16;
|
||||
static uint8_t a,b,c,d,e,f,h,l,cpuTmp;
|
||||
|
||||
//gbs stuff
|
||||
static bool gbsInitRet, gbsPlayRet;
|
||||
|
||||
static uint8_t sub_in_val;
|
||||
static bool irqEnable;
|
||||
static bool cpuHaltLoop,cpuStopLoop,cpuHaltBug;
|
||||
@ -51,6 +55,9 @@ void cpuInit()
|
||||
cpuHaltBug = false;
|
||||
cpuCgbSpeed = false;
|
||||
cpuSetupActionArr();
|
||||
//gbs stuff
|
||||
gbsInitRet = false; //for first init
|
||||
gbsPlayRet = true; //for first play call
|
||||
}
|
||||
|
||||
static void setAImmRegStats()
|
||||
@ -1062,11 +1069,27 @@ void cpuGetInstruction()
|
||||
cpu_arr_pos = 0;
|
||||
return;
|
||||
}
|
||||
if(gbEmuGBSPlayback && pc == 0x8765)
|
||||
if(gbEmuGBSPlayback)
|
||||
{
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return;
|
||||
//init return
|
||||
if(pc == 0x8764)
|
||||
{
|
||||
//if(!gbsInitRet)
|
||||
// printf("Init return\n");
|
||||
gbsInitRet = true; //allow play call
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return;
|
||||
} //play return
|
||||
else if(pc == 0x8765)
|
||||
{
|
||||
//if(!gbsPlayRet)
|
||||
// printf("Play return\n");
|
||||
gbsPlayRet = true; //allow next play call
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(cpuHaltLoop)
|
||||
{
|
||||
@ -1090,8 +1113,8 @@ void cpuGetInstruction()
|
||||
cpu_arr_pos = 0;
|
||||
cpu_action_func = cpu_actions_arr[curInstr];
|
||||
|
||||
//if(pc>=0 && pc<0x30)
|
||||
// printf("%04x %02x hl %04x\n", pc, curInstr, (l|(h<<8)));
|
||||
//if(pc==0xABC || pc == 0xAC1 || pc == 0x5E0E || pc == 0x5E0F)
|
||||
// printf("%04x %02x a %02x b %02x hl %04x\n", pc, curInstr, a, b, (l|(h<<8)));
|
||||
//HALT bug: PC doesnt increase after instruction is parsed!
|
||||
if(!cpuHaltBug) pc++;
|
||||
cpuHaltBug = false;
|
||||
@ -1617,6 +1640,9 @@ void cpuSetSpeed(bool cgb)
|
||||
|
||||
void cpuPlayGBS()
|
||||
{
|
||||
if(!gbsInitRet || !gbsPlayRet)
|
||||
return;
|
||||
gbsPlayRet = false;
|
||||
//push back detect pc
|
||||
sp--;
|
||||
memSet8(sp, 0x87);
|
||||
@ -1645,7 +1671,7 @@ void cpuLoadGBS(uint8_t song)
|
||||
sp--;
|
||||
memSet8(sp, 0x87);
|
||||
sp--;
|
||||
memSet8(sp, 0x65);
|
||||
memSet8(sp, 0x64);
|
||||
//set song and init routine
|
||||
a = song;
|
||||
pc = gbsInitAddr;
|
||||
|
2
main.c
2
main.c
@ -26,7 +26,7 @@
|
||||
#define DEBUG_KEY 0
|
||||
#define DEBUG_LOAD_INFO 1
|
||||
|
||||
static const char *VERSION_STRING = "fixGB Alpha v0.3.2";
|
||||
static const char *VERSION_STRING = "fixGB Alpha v0.4";
|
||||
|
||||
static void gbEmuDisplayFrame(void);
|
||||
static void gbEmuMainLoop(void);
|
||||
|
69
ppu.c
69
ppu.c
@ -83,7 +83,7 @@ void ppuInit()
|
||||
ppuCgbBgPalPos = 0;
|
||||
ppuCgbObjPalPos = 0;
|
||||
ppuCgbBank = 0;
|
||||
ppuLycReg = 153; //last (first) line
|
||||
ppuLycReg = 0; //first line
|
||||
ppuFrameDone = false;
|
||||
ppuVBlank = false;
|
||||
ppuVBlankTriggered = false;
|
||||
@ -177,7 +177,7 @@ bool ppuCycle()
|
||||
ppuOAMpos++;
|
||||
}
|
||||
//draw point?
|
||||
if(ppuClock >= 80 && ppuClock < 240)
|
||||
if(ppuClock >= 92 && ppuClock < 252)
|
||||
{
|
||||
//makes it possible to draw 160x144 in here :)
|
||||
size_t drawPos = (ppuDots*4)+(PPU_Reg[4]*160*4);
|
||||
@ -193,7 +193,9 @@ ppuIncreasePos:
|
||||
{
|
||||
ppuClock = 0;
|
||||
PPU_Reg[4]++;
|
||||
if(PPU_Reg[4]==ppuLycReg)
|
||||
//zelda seems to want a STAT IRQ for line 0 on the line before it which breaks
|
||||
//other games, TODO figure out why its intro looks correct with PPU_Reg == 153
|
||||
if((PPU_Reg[4] == ppuLycReg) || (ppuLycReg == 0 && PPU_Reg[4] == 154))
|
||||
{
|
||||
if(PPU_Reg[1]&PPU_LINEMATCH_IRQ)
|
||||
{
|
||||
@ -280,12 +282,17 @@ uint8_t ppuGet8(uint16_t addr)
|
||||
{
|
||||
if(addr == 0xFF68)
|
||||
val = ppuCgbBgPalPos;
|
||||
else if(addr == 0xFF69)
|
||||
val = PPU_CGB_BGPAL[ppuCgbBgPalPos&0x3F];
|
||||
else if(addr == 0xFF6A)
|
||||
val = ppuCgbObjPalPos;
|
||||
else if(addr == 0xFF6B)
|
||||
val = PPU_CGB_OBJPAL[ppuCgbObjPalPos&0x3F];
|
||||
else if(!(PPU_Reg[0] & PPU_ENABLE) || (ppuMode != 3))
|
||||
{
|
||||
if(addr == 0xFF69)
|
||||
val = PPU_CGB_BGPAL[ppuCgbBgPalPos&0x3F];
|
||||
else if(addr == 0xFF6B)
|
||||
val = PPU_CGB_OBJPAL[ppuCgbObjPalPos&0x3F];
|
||||
}
|
||||
else
|
||||
val = 0xFF;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@ -327,33 +334,41 @@ void ppuSet8(uint16_t addr, uint8_t val)
|
||||
if(addr == 0xFF40 && !(val&PPU_ENABLE))
|
||||
{
|
||||
PPU_Reg[4] = 0;
|
||||
ppuClock = 0;
|
||||
ppuMode = 2;
|
||||
//since it resets a bit into the screen
|
||||
//it wont get through OAM fully
|
||||
ppuClock = 6;
|
||||
ppuOAMpos = 0; //Reset check pos
|
||||
ppuOAM2pos = 0; //Reset array pos
|
||||
ppuMode = 2; //OAM
|
||||
ppuHBlank = false;
|
||||
}
|
||||
else if(addr == 0xFF45)
|
||||
ppuLycReg = ((val == 0 || val > 153) ? 153 : val);
|
||||
// printf("ppuSet8(%04x, %02x)\n",addr,val);
|
||||
ppuLycReg = val;
|
||||
//printf("ppuSet8(%04x, %02x)\n",addr,val);
|
||||
}
|
||||
}
|
||||
else if(addr >= 0xFF68 && addr < 0xFF6C)
|
||||
{
|
||||
if(addr == 0xFF68)
|
||||
ppuCgbBgPalPos = val;
|
||||
else if(addr == 0xFF69)
|
||||
{
|
||||
//printf("BG Write %02x to %02x\n", val, ppuCgbBgPalPos&0x3F);
|
||||
PPU_CGB_BGPAL[ppuCgbBgPalPos&0x3F] = val;
|
||||
if(ppuCgbBgPalPos&0x80) //auto-increment
|
||||
ppuCgbBgPalPos = ((ppuCgbBgPalPos+1)&0x3F)|0x80;
|
||||
}
|
||||
else if(addr == 0xFF6A)
|
||||
ppuCgbObjPalPos = val;
|
||||
else if(addr == 0xFF6B)
|
||||
else if(!(PPU_Reg[0] & PPU_ENABLE) || (ppuMode != 3))
|
||||
{
|
||||
//printf("OBJ Write %02x to %02x\n", val, ppuCgbObjPalPos&0x3F);
|
||||
PPU_CGB_OBJPAL[ppuCgbObjPalPos&0x3F] = val;
|
||||
if(ppuCgbObjPalPos&0x80) //auto-increment
|
||||
ppuCgbObjPalPos = ((ppuCgbObjPalPos+1)&0x3F)|0x80;
|
||||
if(addr == 0xFF69)
|
||||
{
|
||||
//printf("BG Write %02x to %02x\n", val, ppuCgbBgPalPos&0x3F);
|
||||
PPU_CGB_BGPAL[ppuCgbBgPalPos&0x3F] = val;
|
||||
if(ppuCgbBgPalPos&0x80) //auto-increment
|
||||
ppuCgbBgPalPos = ((ppuCgbBgPalPos+1)&0x3F)|0x80;
|
||||
}
|
||||
else if(addr == 0xFF6B)
|
||||
{
|
||||
//printf("OBJ Write %02x to %02x\n", val, ppuCgbObjPalPos&0x3F);
|
||||
PPU_CGB_OBJPAL[ppuCgbObjPalPos&0x3F] = val;
|
||||
if(ppuCgbObjPalPos&0x80) //auto-increment
|
||||
ppuCgbObjPalPos = ((ppuCgbObjPalPos+1)&0x3F)|0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -428,7 +443,6 @@ static uint8_t ppuDoSpritesDMG(uint8_t color, uint8_t tCol)
|
||||
{
|
||||
uint8_t cSpriteByte3 = PPU_OAM2[(i<<2)+3];
|
||||
uint8_t tVal = PPU_OAM2[(i<<2)+2];
|
||||
uint16_t tPos = tVal*16;
|
||||
|
||||
uint8_t OAMcYpos = PPU_OAM2[(i<<2)];
|
||||
uint8_t cmpYPos = OAMcYpos-16;
|
||||
@ -439,12 +453,15 @@ static uint8_t ppuDoSpritesDMG(uint8_t color, uint8_t tCol)
|
||||
cSpriteAdd = 16;
|
||||
cSpriteY &= 7;
|
||||
}
|
||||
if(PPU_Reg[0] & PPU_SPRITE_8_16)
|
||||
tVal &= ~1; //clear low bit since its ALL 8 by 16 (2x the space)
|
||||
if(cSpriteByte3 & PPU_TILE_FLIP_Y)
|
||||
{
|
||||
cSpriteY ^= 7;
|
||||
if(PPU_Reg[0] & PPU_SPRITE_8_16)
|
||||
cSpriteAdd ^= 16; //8 by 16 select
|
||||
}
|
||||
uint16_t tPos = tVal*16;
|
||||
tPos+=(cSpriteY)*2;
|
||||
|
||||
ChrRegA = PPU_VRAM[(tPos+cSpriteAdd)&0x1FFF];
|
||||
@ -578,7 +595,6 @@ static uint16_t ppuDoSpritesCGB(uint8_t color, uint16_t cgbRGB)
|
||||
uint8_t cSpriteByte3 = PPU_OAM2[(i<<2)+3];
|
||||
uint16_t tCgbBank = (cSpriteByte3&PPU_TILE_CGB_BANK)?0x2000:0x0;
|
||||
uint8_t tVal = PPU_OAM2[(i<<2)+2];
|
||||
uint16_t tPos = tVal*16;
|
||||
|
||||
uint8_t OAMcYpos = PPU_OAM2[(i<<2)];
|
||||
uint8_t cmpYPos = OAMcYpos-16;
|
||||
@ -589,12 +605,15 @@ static uint16_t ppuDoSpritesCGB(uint8_t color, uint16_t cgbRGB)
|
||||
cSpriteAdd = 16;
|
||||
cSpriteY &= 7;
|
||||
}
|
||||
if(PPU_Reg[0] & PPU_SPRITE_8_16)
|
||||
tVal &= ~1; //clear low bit since its ALL 8 by 16 (2x the space)
|
||||
if(cSpriteByte3 & PPU_TILE_FLIP_Y)
|
||||
{
|
||||
cSpriteY ^= 7;
|
||||
if(PPU_Reg[0] & PPU_SPRITE_8_16)
|
||||
cSpriteAdd ^= 16; //8 by 16 select
|
||||
}
|
||||
uint16_t tPos = tVal*16;
|
||||
tPos+=(cSpriteY)*2;
|
||||
|
||||
ChrRegA = PPU_VRAM[tCgbBank|((tPos+cSpriteAdd)&0x1FFF)];
|
||||
|
Loading…
Reference in New Issue
Block a user