mirror of
https://github.com/libretro/fixGB.git
synced 2025-02-20 01:42:18 +00:00
-dont close emu when opening with unsupported file or no file at all, display error message instead
-dont close emu on invalid cpu instruction, freeze game instead until a button is pressed -set window title more proper -display currently playing .gbs track on screen rather than just on the console via bitmap font
This commit is contained in:
parent
ea19c06579
commit
bffa0e6666
4
apu.c
4
apu.c
@ -152,11 +152,11 @@ void apuDeinitBufs()
|
||||
apuOutBuf = NULL;
|
||||
}
|
||||
|
||||
extern bool allowCgbRegs;
|
||||
extern bool gbCgbMode;
|
||||
void apuInit()
|
||||
{
|
||||
memset(APU_IO_Reg,0,0x50);
|
||||
if(allowCgbRegs) //essentially 50% duty pulse on CGB
|
||||
if(gbCgbMode) //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);
|
||||
|
80
cpu.c
80
cpu.c
@ -26,7 +26,7 @@ extern uint16_t gbsInitAddr;
|
||||
extern uint16_t gbsPlayAddr;
|
||||
extern uint16_t gbsSP;
|
||||
extern uint8_t cpuTimer;
|
||||
extern bool allowCgbRegs;
|
||||
extern bool gbCgbMode;
|
||||
|
||||
//used externally
|
||||
bool cpuDoStopSwitch = false;
|
||||
@ -41,11 +41,11 @@ static bool gbsInitRet, gbsPlayRet;
|
||||
|
||||
static uint8_t sub_in_val;
|
||||
static bool irqEnable;
|
||||
static bool cpuHaltLoop,cpuStopLoop,cpuHaltBug;
|
||||
static bool cpuHaltLoop,cpuStopLoop,cpuHaltBug,cpuPrevInAny;
|
||||
void cpuInit()
|
||||
{
|
||||
sub_in_val=0,cpuTmp=0,cpuTmp16=0;
|
||||
if(allowCgbRegs) //From GBC Bootrom
|
||||
if(gbCgbMode) //From GBC Bootrom
|
||||
a=0x11,b=0,c=0,d=0,e=0x08,f=0x80,h=0,l=0x7C;
|
||||
else //From GB Bootrom
|
||||
a=0x01,b=0,c=0x13,d=0,e=0xD8,f=0xB0,h=1,l=0x4D;
|
||||
@ -56,6 +56,7 @@ void cpuInit()
|
||||
cpuStopLoop = false;
|
||||
cpuHaltBug = false;
|
||||
cpuCgbSpeed = false;
|
||||
cpuPrevInAny = false;
|
||||
cpuSetupActionArr();
|
||||
//gbs stuff
|
||||
gbsInitRet = false; //for first init
|
||||
@ -597,6 +598,12 @@ void cpuDAA(uint8_t *reg)
|
||||
*reg = (uint8_t)in;
|
||||
}
|
||||
|
||||
static void cpuSetStopLoop()
|
||||
{
|
||||
printf("CPU: Frozen until Button is pressed\n");
|
||||
cpuStopLoop = true;
|
||||
}
|
||||
|
||||
static void cpuSTOP(uint8_t *none)
|
||||
{
|
||||
(void)none;
|
||||
@ -607,7 +614,7 @@ static void cpuSTOP(uint8_t *none)
|
||||
cpuDoStopSwitch = false;
|
||||
}
|
||||
else
|
||||
cpuStopLoop = true;
|
||||
cpuSetStopLoop();
|
||||
//takes up 2 instructions?
|
||||
pc++;
|
||||
}
|
||||
@ -1065,13 +1072,13 @@ bool cpuHandleIrqUpdates()
|
||||
return false;
|
||||
}
|
||||
static uint8_t curInstr;
|
||||
bool cpuGetInstruction()
|
||||
void cpuGetInstruction()
|
||||
{
|
||||
if(cpuHandleIrqUpdates())
|
||||
{
|
||||
cpuHaltLoop = false;
|
||||
cpu_arr_pos = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if(gbEmuGBSPlayback)
|
||||
{
|
||||
@ -1083,7 +1090,7 @@ bool cpuGetInstruction()
|
||||
gbsInitRet = true; //allow play call
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return true;
|
||||
return;
|
||||
} //play return
|
||||
else if(pc == 0x8765)
|
||||
{
|
||||
@ -1092,7 +1099,7 @@ bool cpuGetInstruction()
|
||||
gbsPlayRet = true; //allow next play call
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(cpuHaltLoop)
|
||||
@ -1102,50 +1109,50 @@ bool cpuGetInstruction()
|
||||
cpuHaltLoop = false;
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if(cpuStopLoop)
|
||||
{
|
||||
if(inputAny())
|
||||
bool cpuInAny = inputAny();
|
||||
if(cpuInAny && !cpuPrevInAny)
|
||||
cpuStopLoop = false;
|
||||
cpuPrevInAny = cpuInAny;
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpu_arr_pos = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
curInstr = memGet8(pc);
|
||||
cpu_action_arr = cpu_instr_arr[curInstr];
|
||||
if(cpu_action_arr == NULL)
|
||||
{
|
||||
printf("Unsupported Instruction at %04x:%02x!\n", pc-1,curInstr);
|
||||
return false;
|
||||
printf("CPU Error: Unsupported Instruction at %04x:%02x!\n", pc-1,curInstr);
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpuSetStopLoop();
|
||||
}
|
||||
cpu_arr_pos = 0;
|
||||
cpu_action_func = cpu_actions_arr[curInstr];
|
||||
|
||||
|
||||
//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;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Main CPU Interpreter */
|
||||
bool cpuDmaHalt = false;
|
||||
|
||||
bool cpuCycle()
|
||||
void cpuCycle()
|
||||
{
|
||||
bool cycleret = true;
|
||||
if(cpuDmaHalt)
|
||||
return cycleret;
|
||||
return;
|
||||
uint8_t cpu_action, sub_instr;
|
||||
cpu_action = cpu_action_arr[cpu_arr_pos];
|
||||
cpu_arr_pos++;
|
||||
switch(cpu_action)
|
||||
{
|
||||
case CPU_GET_INSTRUCTION:
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_GET_SUBINSTRUCTION:
|
||||
sub_instr = memGet8(pc++);
|
||||
@ -1180,8 +1187,10 @@ bool cpuCycle()
|
||||
cpu_action_arr = cpu_imm_a_arr;
|
||||
break;
|
||||
default: //should never happen
|
||||
printf("Unknown sub %02x\n", sub_instr);
|
||||
return false;
|
||||
printf("CPU Error: Unknown sub %02x\n", sub_instr);
|
||||
cpu_action_arr = cpu_nop_arr;
|
||||
cpuSetStopLoop();
|
||||
break;
|
||||
}
|
||||
//set sub func
|
||||
switch(sub_instr>>3)
|
||||
@ -1234,35 +1243,35 @@ bool cpuCycle()
|
||||
break;
|
||||
case CPU_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&cpuTmp);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_A_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&a);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_B_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&b);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_C_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&c);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_D_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&d);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_E_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&e);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_H_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&h);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_L_ACTION_GET_INSTRUCTION:
|
||||
cpu_action_func(&l);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_ACTION_WRITE:
|
||||
cpu_action_func(&cpuTmp);
|
||||
@ -1568,27 +1577,27 @@ bool cpuCycle()
|
||||
case CPU_DI_GET_INSTRUCTION:
|
||||
//printf("Disabled IRQs at %04x\n", pc);
|
||||
irqEnable = false;
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_EI_GET_INSTRUCTION:
|
||||
//printf("Enabled IRQs and jmp to %04x ",pc);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
//printf("%04x\n",pc);
|
||||
irqEnable = true;
|
||||
break;
|
||||
case CPU_SCF_GET_INSTRUCTION:
|
||||
f |= P_FLAG_C;
|
||||
f &= ~(P_FLAG_H|P_FLAG_N);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_CCF_GET_INSTRUCTION:
|
||||
f ^= P_FLAG_C;
|
||||
f &= ~(P_FLAG_H|P_FLAG_N);
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_PC_FROM_HL_GET_INSTRUCTION:
|
||||
pc = (l|(h<<8));
|
||||
cycleret = cpuGetInstruction();
|
||||
cpuGetInstruction();
|
||||
break;
|
||||
case CPU_PC_FROM_T16:
|
||||
pc = cpuTmp16;
|
||||
@ -1606,7 +1615,6 @@ bool cpuCycle()
|
||||
if(!(f & P_FLAG_C)) cpu_arr_pos+=3;
|
||||
break;
|
||||
}
|
||||
return cycleret;
|
||||
}
|
||||
|
||||
uint16_t cpuCurPC()
|
||||
|
2
cpu.h
2
cpu.h
@ -9,7 +9,7 @@
|
||||
#define _cpu_h_
|
||||
|
||||
void cpuInit();
|
||||
bool cpuCycle();
|
||||
void cpuCycle();
|
||||
uint16_t cpuCurPC();
|
||||
void cpuSetSpeed(bool cgb);
|
||||
void cpuLoadGBS(uint8_t song);
|
||||
|
2
input.c
2
input.c
@ -28,7 +28,7 @@ void inputSet8(uint16_t addr, uint8_t in)
|
||||
(void)addr;
|
||||
modeSelect = ((in)>>4)&0x3;
|
||||
#if DEBUG_INPUT
|
||||
printf("Set %02x->%02x\n",in,modeSelect);
|
||||
printf("Input: Set %02x->%02x\n",in,modeSelect);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
156
main.c
156
main.c
@ -26,7 +26,10 @@
|
||||
#define DEBUG_KEY 0
|
||||
#define DEBUG_LOAD_INFO 1
|
||||
|
||||
static const char *VERSION_STRING = "fixGB Alpha v0.5.4";
|
||||
static const char *VERSION_STRING = "fixGB Alpha v0.5.5";
|
||||
static char window_title[256];
|
||||
static char window_title_pause[256];
|
||||
static int window_handle = -1;
|
||||
|
||||
static void gbEmuDisplayFrame(void);
|
||||
static void gbEmuMainLoop(void);
|
||||
@ -40,9 +43,8 @@ static void gbEmuHandleSpecialUp(int key, int x, int y);
|
||||
uint8_t *emuGBROM = NULL;
|
||||
char *emuSaveName = NULL;
|
||||
//used externally
|
||||
uint32_t textureImage[0x9A00];
|
||||
bool nesPause = false;
|
||||
bool ppuDebugPauseFrame = false;
|
||||
uint32_t textureImage[0x5A00];
|
||||
bool gbPause = false;
|
||||
bool gbEmuGBSPlayback = false;
|
||||
bool gbsTimerMode = false;
|
||||
uint16_t gbsLoadAddr = 0;
|
||||
@ -52,7 +54,7 @@ uint32_t gbsRomSize = 0;
|
||||
uint16_t gbsSP = 0;
|
||||
uint8_t gbsTracksTotal = 0, gbsTMA = 0, gbsTAC = 0;
|
||||
uint8_t cpuTimer = 3;
|
||||
bool allowCgbRegs = false;
|
||||
bool gbCgbMode = false;
|
||||
|
||||
static bool inPause = false;
|
||||
static bool inResize = false;
|
||||
@ -77,6 +79,7 @@ static DWORD emuMainTotalElapsed = 0;
|
||||
#define VISIBLE_DOTS 160
|
||||
#define VISIBLE_LINES 144
|
||||
|
||||
static uint32_t linesToDraw = VISIBLE_LINES;
|
||||
static const uint32_t visibleImg = VISIBLE_DOTS*VISIBLE_LINES*4;
|
||||
static uint8_t scaleFactor = 3;
|
||||
static uint32_t mainLoopRuns;
|
||||
@ -87,10 +90,18 @@ extern uint8_t inValReads[8];
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
puts(VERSION_STRING);
|
||||
strcpy(window_title, VERSION_STRING);
|
||||
memset(textureImage,0,visibleImg);
|
||||
if(argc >= 2 && (strstr(argv[1],".gbs") != NULL || strstr(argv[1],".GBS") != NULL))
|
||||
{
|
||||
FILE *gbF = fopen(argv[1],"rb");
|
||||
if(!gbF) return EXIT_SUCCESS;
|
||||
if(!gbF)
|
||||
{
|
||||
printf("Main: Could not open %s!\n", argv[1]);
|
||||
puts("Press enter to exit");
|
||||
getc(stdin);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
fseek(gbF,0,SEEK_END);
|
||||
size_t fsize = ftell(gbF);
|
||||
rewind(gbF);
|
||||
@ -112,14 +123,14 @@ int main(int argc, char** argv)
|
||||
if(gbsTAC&0x80)
|
||||
{
|
||||
cpuSetSpeed(true);
|
||||
allowCgbRegs = true;
|
||||
gbCgbMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuSetSpeed(false);
|
||||
allowCgbRegs = false;
|
||||
gbCgbMode = false;
|
||||
}
|
||||
printf("Main: CGB Regs are %sallowed\n", allowCgbRegs?"":"dis");
|
||||
printf("Main: CGB Regs are %sallowed\n", gbCgbMode?"":"dis");
|
||||
if(gbsTAC&4)
|
||||
{
|
||||
printf("Main: GBS Play Timing: Timer\n");
|
||||
@ -132,19 +143,30 @@ int main(int argc, char** argv)
|
||||
}
|
||||
memInit(true,true);
|
||||
if(tmpROM[0x10] != 0)
|
||||
{
|
||||
printf("Game: %.32s\n",(char*)(tmpROM+0x10));
|
||||
sprintf(window_title, "%.32s (GBS) - %s\n", (char*)(tmpROM+0x10), VERSION_STRING);
|
||||
}
|
||||
free(tmpROM);
|
||||
printf("Read in %s\n", argv[1]);
|
||||
apuInitBufs();
|
||||
//does all inits for us
|
||||
memStartGBS();
|
||||
gbEmuGBSPlayback = true;
|
||||
linesToDraw = 20;
|
||||
scaleFactor = 4;
|
||||
}
|
||||
else if(argc >= 2 && (strstr(argv[1],".gbc") != NULL || strstr(argv[1],".GBC") != NULL
|
||||
|| strstr(argv[1],".gb") != NULL || strstr(argv[1],".GB") != NULL))
|
||||
{
|
||||
FILE *gbF = fopen(argv[1],"rb");
|
||||
if(!gbF) return EXIT_SUCCESS;
|
||||
if(!gbF)
|
||||
{
|
||||
printf("Main: Could not open %s!\n", argv[1]);
|
||||
puts("Press enter to exit");
|
||||
getc(stdin);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
fseek(gbF,0,SEEK_END);
|
||||
size_t fsize = ftell(gbF);
|
||||
rewind(gbF);
|
||||
@ -152,7 +174,9 @@ int main(int argc, char** argv)
|
||||
if(emuGBROM == NULL)
|
||||
{
|
||||
printf("Main: Unable to allocate ROM space...\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
puts("Press enter to exit");
|
||||
getc(stdin);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
fread(emuGBROM,1,fsize,gbF);
|
||||
fclose(gbF);
|
||||
@ -169,13 +193,14 @@ int main(int argc, char** argv)
|
||||
memcpy(emuSaveName+strlen(argv[1])-2,"sav",4);
|
||||
}
|
||||
//Set CGB Regs allowed
|
||||
allowCgbRegs = (emuGBROM[0x143] == 0x80 || emuGBROM[0x143] == 0xC0);
|
||||
printf("Main: CGB Regs are %sallowed\n", allowCgbRegs?"":"dis");
|
||||
gbCgbMode = (emuGBROM[0x143] == 0x80 || emuGBROM[0x143] == 0xC0);
|
||||
printf("Main: CGB Regs are %sallowed\n", gbCgbMode?"":"dis");
|
||||
if(!memInit(true,false))
|
||||
{
|
||||
free(emuGBROM);
|
||||
printf("Exit...\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
puts("Press enter to exit");
|
||||
getc(stdin);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
//CPU DMG Mode
|
||||
cpuSetSpeed(false);
|
||||
@ -185,11 +210,28 @@ int main(int argc, char** argv)
|
||||
apuInit();
|
||||
inputInit();
|
||||
if(emuGBROM[0x134] != 0)
|
||||
printf("Game: %.11s\n", (char*)(emuGBROM+0x134));
|
||||
{
|
||||
if(gbCgbMode)
|
||||
{
|
||||
printf("Game: %.11s\n", (char*)(emuGBROM+0x134));
|
||||
sprintf(window_title, "%.11s (CGB) - %s\n", (char*)(emuGBROM+0x134), VERSION_STRING);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Game: %.16s\n", (char*)(emuGBROM+0x134));
|
||||
sprintf(window_title, "%.16s (DMG) - %s\n", (char*)(emuGBROM+0x134), VERSION_STRING);
|
||||
}
|
||||
}
|
||||
printf("Read in %s\n", argv[1]);
|
||||
}
|
||||
if(emuGBROM == NULL)
|
||||
{
|
||||
printf("Main: No File to Open! Make sure to call fixGB with a .gb/.gbc/.gbs File as Argument.\n");
|
||||
puts("Press enter to exit");
|
||||
getc(stdin);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
sprintf(window_title_pause, "%s (Pause)", window_title);
|
||||
#if WINDOWS_BUILD
|
||||
#if DEBUG_HZ
|
||||
emuFrameStart = GetTickCount();
|
||||
@ -198,14 +240,13 @@ int main(int argc, char** argv)
|
||||
emuMainFrameStart = GetTickCount();
|
||||
#endif
|
||||
#endif
|
||||
memset(textureImage,0,visibleImg);
|
||||
//do one scanline per idle loop
|
||||
mainLoopRuns = 70224;
|
||||
mainLoopPos = mainLoopRuns;
|
||||
glutInit(&argc, argv);
|
||||
glutInitWindowSize(VISIBLE_DOTS*scaleFactor, VISIBLE_LINES*scaleFactor);
|
||||
glutInitWindowSize(VISIBLE_DOTS*scaleFactor, linesToDraw*scaleFactor);
|
||||
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
|
||||
glutCreateWindow(VERSION_STRING);
|
||||
window_handle = glutCreateWindow(gbPause ? window_title_pause : window_title);
|
||||
audioInit();
|
||||
atexit(&gbEmuDeinit);
|
||||
glutKeyboardFunc(&gbEmuHandleKeyDown);
|
||||
@ -220,7 +261,7 @@ int main(int argc, char** argv)
|
||||
wglSwapIntervalEXT(1);
|
||||
#endif
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, VISIBLE_DOTS, VISIBLE_LINES, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureImage);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, VISIBLE_DOTS, linesToDraw, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureImage);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
@ -248,6 +289,9 @@ static void gbEmuDeinit(void)
|
||||
if(emuSaveName != NULL)
|
||||
free(emuSaveName);
|
||||
emuSaveName = NULL;
|
||||
if(window_handle >= 0)
|
||||
glutDestroyWindow(window_handle);
|
||||
window_handle = -1;
|
||||
//printf("Bye!\n");
|
||||
}
|
||||
|
||||
@ -263,7 +307,7 @@ static void gbEmuMainLoop(void)
|
||||
//do one scanline loop
|
||||
do
|
||||
{
|
||||
if((!emuSkipVsync && emuRenderFrame) || nesPause)
|
||||
if((!emuSkipVsync && emuRenderFrame) || gbPause)
|
||||
{
|
||||
#if (WINDOWS_BUILD && DEBUG_MAIN_CALLS)
|
||||
emuMainTimesSkipped++;
|
||||
@ -288,11 +332,7 @@ static void gbEmuMainLoop(void)
|
||||
if(!(mainClock&cpuTimer))
|
||||
{
|
||||
//main CPU clock
|
||||
if(!cpuCycle())
|
||||
{
|
||||
//memDumpMainMem();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
cpuCycle();
|
||||
//mem clock tied to CPU clock, so
|
||||
//double speed in CGB mode!
|
||||
if(!(memClock&3))
|
||||
@ -300,31 +340,26 @@ static void gbEmuMainLoop(void)
|
||||
memClock++;
|
||||
}
|
||||
//run PPU last
|
||||
if(!ppuCycle())
|
||||
exit(EXIT_SUCCESS);
|
||||
ppuCycle();
|
||||
if(ppuDrawDone())
|
||||
{
|
||||
if(!gbEmuGBSPlayback)
|
||||
emuRenderFrame = true;
|
||||
//update console stats if requested
|
||||
#if (WINDOWS_BUILD && DEBUG_HZ)
|
||||
emuTimesCalled++;
|
||||
DWORD end = GetTickCount();
|
||||
emuTotalElapsed += end - emuFrameStart;
|
||||
if(emuTotalElapsed >= 1000)
|
||||
{
|
||||
emuRenderFrame = true;
|
||||
//update console stats if requested
|
||||
#if (WINDOWS_BUILD && DEBUG_HZ)
|
||||
emuTimesCalled++;
|
||||
DWORD end = GetTickCount();
|
||||
emuTotalElapsed += end - emuFrameStart;
|
||||
if(emuTotalElapsed >= 1000)
|
||||
{
|
||||
printf("\r%iHz ", emuTimesCalled);
|
||||
emuTimesCalled = 0;
|
||||
emuTotalElapsed = 0;
|
||||
}
|
||||
emuFrameStart = end;
|
||||
#endif
|
||||
glutPostRedisplay();
|
||||
if(ppuDebugPauseFrame)
|
||||
nesPause = true;
|
||||
printf("\r%iHz ", emuTimesCalled);
|
||||
emuTimesCalled = 0;
|
||||
emuTotalElapsed = 0;
|
||||
}
|
||||
else if(!gbsTimerMode)
|
||||
emuFrameStart = end;
|
||||
#endif
|
||||
glutPostRedisplay();
|
||||
//send VSync to GBS Player if required
|
||||
if(gbEmuGBSPlayback && !gbsTimerMode)
|
||||
cpuPlayGBS();
|
||||
}
|
||||
mainClock++;
|
||||
@ -399,70 +434,71 @@ static void gbEmuHandleKeyDown(unsigned char key, int x, int y)
|
||||
printf("pause\n");
|
||||
#endif
|
||||
inPause = true;
|
||||
nesPause ^= true;
|
||||
gbPause ^= true;
|
||||
glutSetWindowTitle(gbPause ? window_title_pause : window_title);
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*1, VISIBLE_LINES*1);
|
||||
glutReshapeWindow(VISIBLE_DOTS*1, linesToDraw*1);
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*2, VISIBLE_LINES*2);
|
||||
glutReshapeWindow(VISIBLE_DOTS*2, linesToDraw*2);
|
||||
}
|
||||
break;
|
||||
case '3':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*3, VISIBLE_LINES*3);
|
||||
glutReshapeWindow(VISIBLE_DOTS*3, linesToDraw*3);
|
||||
}
|
||||
break;
|
||||
case '4':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*4, VISIBLE_LINES*4);
|
||||
glutReshapeWindow(VISIBLE_DOTS*4, linesToDraw*4);
|
||||
}
|
||||
break;
|
||||
case '5':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*5, VISIBLE_LINES*5);
|
||||
glutReshapeWindow(VISIBLE_DOTS*5, linesToDraw*5);
|
||||
}
|
||||
break;
|
||||
case '6':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*6, VISIBLE_LINES*6);
|
||||
glutReshapeWindow(VISIBLE_DOTS*6, linesToDraw*6);
|
||||
}
|
||||
break;
|
||||
case '7':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*7, VISIBLE_LINES*7);
|
||||
glutReshapeWindow(VISIBLE_DOTS*7, linesToDraw*7);
|
||||
}
|
||||
break;
|
||||
case '8':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*8, VISIBLE_LINES*8);
|
||||
glutReshapeWindow(VISIBLE_DOTS*8, linesToDraw*8);
|
||||
}
|
||||
break;
|
||||
case '9':
|
||||
if(!inResize)
|
||||
{
|
||||
inResize = true;
|
||||
glutReshapeWindow(VISIBLE_DOTS*9, VISIBLE_LINES*9);
|
||||
glutReshapeWindow(VISIBLE_DOTS*9, linesToDraw*9);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -606,7 +642,7 @@ static void gbEmuDisplayFrame()
|
||||
emuRenderFrame = false;
|
||||
return;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, VISIBLE_DOTS, VISIBLE_LINES, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureImage);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, VISIBLE_DOTS, linesToDraw, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureImage);
|
||||
emuRenderFrame = false;
|
||||
}
|
||||
|
||||
@ -618,10 +654,10 @@ static void gbEmuDisplayFrame()
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
double upscaleVal = round((((double)glutGet(GLUT_WINDOW_HEIGHT))/((double)VISIBLE_LINES))*20.0)/20.0;
|
||||
double upscaleVal = round((((double)glutGet(GLUT_WINDOW_HEIGHT))/((double)linesToDraw))*20.0)/20.0;
|
||||
double windowMiddle = ((double)glutGet(GLUT_WINDOW_WIDTH))/2.0;
|
||||
double drawMiddle = (((double)VISIBLE_DOTS)*upscaleVal)/2.0;
|
||||
double drawHeight = ((double)VISIBLE_LINES)*upscaleVal;
|
||||
double drawHeight = ((double)linesToDraw)*upscaleVal;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0,0); glVertex2f(windowMiddle-drawMiddle,drawHeight);
|
||||
|
2
mbc.c
2
mbc.c
@ -96,7 +96,7 @@ void mbcInit(uint8_t type)
|
||||
{
|
||||
mbcGetRAM8 = mbc2GetExtRAM8;
|
||||
mbcSetRAM8 = mbc2SetExtRAM8;
|
||||
printf("MBC Set Special MBC2 RAM Functions\n");
|
||||
printf("MBC: Set Special MBC2 RAM Functions\n");
|
||||
}
|
||||
else if(extTotalSize < 0x2000)
|
||||
{
|
||||
|
47
mem.c
47
mem.c
@ -48,7 +48,7 @@ static bool timerRegEnable = false;
|
||||
static bool emuSaveEnabled = false;
|
||||
|
||||
//from main.c
|
||||
extern bool allowCgbRegs;
|
||||
extern bool gbCgbMode;
|
||||
extern uint8_t *emuGBROM;
|
||||
|
||||
//from mbc.c
|
||||
@ -390,7 +390,7 @@ bool memInit(bool romcheck, bool gbs)
|
||||
memLoadSave();
|
||||
break;
|
||||
default:
|
||||
printf("Mem: Unsupported Type %02x!\n", emuGBROM[0x147]);
|
||||
printf("Mem Error: Unsupported MBC Type %02x!\n", emuGBROM[0x147]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -444,8 +444,8 @@ bool memInit(bool romcheck, bool gbs)
|
||||
}
|
||||
else if(addr < 0xA000) //PPU VRAM
|
||||
{
|
||||
memGet8ptr[addr] = allowCgbRegs?ppuGetVRAMBank8:ppuGetVRAMNoBank8;
|
||||
memSet8ptr[addr] = allowCgbRegs?ppuSetVRAMBank8:ppuSetVRAMNoBank8;
|
||||
memGet8ptr[addr] = gbCgbMode?ppuGetVRAMBank8:ppuGetVRAMNoBank8;
|
||||
memSet8ptr[addr] = gbCgbMode?ppuSetVRAMBank8:ppuSetVRAMNoBank8;
|
||||
}
|
||||
else if(addr < 0xC000) //Cardridge RAM
|
||||
{
|
||||
@ -459,8 +459,8 @@ bool memInit(bool romcheck, bool gbs)
|
||||
}
|
||||
else if(addr < 0xE000) //Main RAM (possibly banked)
|
||||
{
|
||||
memGet8ptr[addr] = allowCgbRegs?memGetRAMBank8:memGetRAMNoBank8;
|
||||
memSet8ptr[addr] = allowCgbRegs?memSetRAMBank8:memSetRAMNoBank8;
|
||||
memGet8ptr[addr] = gbCgbMode?memGetRAMBank8:memGetRAMNoBank8;
|
||||
memSet8ptr[addr] = gbCgbMode?memSetRAMBank8:memSetRAMNoBank8;
|
||||
}
|
||||
else if(addr < 0xF000) //Echo Main RAM
|
||||
{
|
||||
@ -469,8 +469,8 @@ bool memInit(bool romcheck, bool gbs)
|
||||
}
|
||||
else if(addr < 0xFE00) //Echo Main RAM (possibly banked)
|
||||
{
|
||||
memGet8ptr[addr] = allowCgbRegs?memGetRAMBank8:memGetRAMNoBank8;
|
||||
memSet8ptr[addr] = allowCgbRegs?memSetRAMBank8:memSetRAMNoBank8;
|
||||
memGet8ptr[addr] = gbCgbMode?memGetRAMBank8:memGetRAMNoBank8;
|
||||
memSet8ptr[addr] = gbCgbMode?memSetRAMBank8:memSetRAMNoBank8;
|
||||
}
|
||||
else if(addr < 0xFEA0) //PPU OAM
|
||||
{
|
||||
@ -504,13 +504,13 @@ bool memInit(bool romcheck, bool gbs)
|
||||
}
|
||||
else if(addr < 0xFF68) //General CGB Features
|
||||
{
|
||||
memGet8ptr[addr] = allowCgbRegs?memGetGeneralReg8:memGetInvalid8;
|
||||
memSet8ptr[addr] = allowCgbRegs?memSetGeneralReg8:memSetInvalid8;
|
||||
memGet8ptr[addr] = gbCgbMode?memGetGeneralReg8:memGetInvalid8;
|
||||
memSet8ptr[addr] = gbCgbMode?memSetGeneralReg8:memSetInvalid8;
|
||||
}
|
||||
else if(addr < 0xFF6C) //PPU CGB Regs
|
||||
{
|
||||
memGet8ptr[addr] = allowCgbRegs?ppuGetReg8:memGetInvalid8;
|
||||
memSet8ptr[addr] = allowCgbRegs?ppuSetReg8:memSetInvalid8;
|
||||
memGet8ptr[addr] = gbCgbMode?ppuGetReg8:memGetInvalid8;
|
||||
memSet8ptr[addr] = gbCgbMode?ppuSetReg8:memSetInvalid8;
|
||||
}
|
||||
else if(addr < 0xFF80) //General CGB Features
|
||||
{
|
||||
@ -528,7 +528,7 @@ bool memInit(bool romcheck, bool gbs)
|
||||
memSet8ptr[addr] = memSetGeneralReg8;
|
||||
}
|
||||
else //Should never happen
|
||||
printf("MEM WARNING: Address %04x uninitialized!\n", addr);
|
||||
printf("Mem Warning: Address %04x uninitialized!\n", addr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -536,7 +536,8 @@ bool memInit(bool romcheck, bool gbs)
|
||||
void memStartGBS()
|
||||
{
|
||||
curGBS = 1;
|
||||
printf("Track %i/%i ", curGBS, gbsTracksTotal);
|
||||
//printf("Track %i/%i ", curGBS, gbsTracksTotal);
|
||||
ppuDrawGBSTrackNum(curGBS, gbsTracksTotal);
|
||||
cpuLoadGBS(curGBS-1);
|
||||
}
|
||||
|
||||
@ -630,15 +631,15 @@ static uint8_t memGetGeneralReg8(uint16_t addr)
|
||||
case 0x56:
|
||||
return irReq|0x3C;
|
||||
case 0x6C:
|
||||
return (!(allowCgbRegs))|0xFE;
|
||||
return (!(gbCgbMode))|0xFE;
|
||||
case 0x70:
|
||||
return (allowCgbRegs)?(cgbMainBank|0xF8):0xFF;
|
||||
return (gbCgbMode)?(cgbMainBank|0xF8):0xFF;
|
||||
case 0x72:
|
||||
return genericReg[0];
|
||||
case 0x73:
|
||||
return genericReg[1];
|
||||
case 0x74:
|
||||
return (allowCgbRegs)?genericReg[2]:0xFF;
|
||||
return (gbCgbMode)?genericReg[2]:0xFF;
|
||||
case 0x75:
|
||||
return genericReg[3]|0x8F;
|
||||
case 0x76:
|
||||
@ -748,7 +749,7 @@ static void memSetGeneralReg8(uint16_t addr, uint8_t val)
|
||||
case 0x56:
|
||||
irReq = val;
|
||||
case 0x70:
|
||||
if(allowCgbRegs)
|
||||
if(gbCgbMode)
|
||||
{
|
||||
cgbMainBank = (val&7);
|
||||
if(cgbMainBank == 0)
|
||||
@ -762,7 +763,7 @@ static void memSetGeneralReg8(uint16_t addr, uint8_t val)
|
||||
genericReg[1] = val;
|
||||
break;
|
||||
case 0x74:
|
||||
if(allowCgbRegs)
|
||||
if(gbCgbMode)
|
||||
genericReg[2] = val;
|
||||
break;
|
||||
case 0x75:
|
||||
@ -790,7 +791,7 @@ void memDumpMainMem()
|
||||
FILE *f = fopen("MainMem.bin","wb");
|
||||
if(f)
|
||||
{
|
||||
fwrite(Main_Mem,1,allowCgbRegs?0x8000:0x2000,f);
|
||||
fwrite(Main_Mem,1,gbCgbMode?0x8000:0x2000,f);
|
||||
fclose(f);
|
||||
}
|
||||
f = fopen("HighMem.bin","wb");
|
||||
@ -860,7 +861,8 @@ void memClockTimers()
|
||||
curGBS++;
|
||||
if(curGBS > gbsTracksTotal)
|
||||
curGBS = 1;
|
||||
printf("\rTrack %i/%i ", curGBS, gbsTracksTotal);
|
||||
//printf("\rTrack %i/%i ", curGBS, gbsTracksTotal);
|
||||
ppuDrawGBSTrackNum(curGBS, gbsTracksTotal);
|
||||
cpuLoadGBS(curGBS-1);
|
||||
}
|
||||
else if(!inValReads[BUTTON_RIGHT])
|
||||
@ -872,7 +874,8 @@ void memClockTimers()
|
||||
curGBS--;
|
||||
if(curGBS < 1)
|
||||
curGBS = gbsTracksTotal;
|
||||
printf("\rTrack %i/%i ", curGBS, gbsTracksTotal);
|
||||
//printf("\rTrack %i/%i ", curGBS, gbsTracksTotal);
|
||||
ppuDrawGBSTrackNum(curGBS, gbsTracksTotal);
|
||||
cpuLoadGBS(curGBS-1);
|
||||
}
|
||||
else if(!inValReads[BUTTON_LEFT])
|
||||
|
112
ppu.c
112
ppu.c
@ -46,8 +46,8 @@ typedef void (*drawFunc)(size_t);
|
||||
static drawFunc ppuDrawDot = NULL;
|
||||
|
||||
//from main.c
|
||||
extern uint32_t textureImage[0x9A00];
|
||||
extern bool allowCgbRegs;
|
||||
extern uint32_t textureImage[0x5A00];
|
||||
extern bool gbCgbMode;
|
||||
//used externally
|
||||
uint8_t ppuCgbBank = 0;
|
||||
|
||||
@ -92,7 +92,7 @@ static const uint8_t defaultCGBObjPal[0x40] = {
|
||||
void ppuInit()
|
||||
{
|
||||
//Set start line
|
||||
if(allowCgbRegs)
|
||||
if(gbCgbMode)
|
||||
{
|
||||
ppuClock = 170;
|
||||
ppuMode = 1;
|
||||
@ -117,7 +117,7 @@ void ppuInit()
|
||||
ppuHBlank = false;
|
||||
ppuHBlankTriggered = false;
|
||||
//set draw method depending on DMG or CGB Mode
|
||||
ppuDrawDot = allowCgbRegs?ppuDrawDotCGB:ppuDrawDotDMG;
|
||||
ppuDrawDot = gbCgbMode?ppuDrawDotCGB:ppuDrawDotDMG;
|
||||
//init buffers
|
||||
memset(PPU_Reg,0,12);
|
||||
memset(PPU_OAM,0,0xA0);
|
||||
@ -159,12 +159,12 @@ void ppuInit()
|
||||
}
|
||||
|
||||
extern bool gbEmuGBSPlayback;
|
||||
bool ppuCycle()
|
||||
void ppuCycle()
|
||||
{
|
||||
if(gbEmuGBSPlayback)
|
||||
goto ppuIncreasePos;
|
||||
if(!(PPU_Reg[0] & PPU_ENABLE))
|
||||
return true;
|
||||
return;
|
||||
//Update line match stat
|
||||
ppuLineMatch = ((PPU_Reg[4] == PPU_Reg[5]) ? PPU_LINEMATCH : 0);
|
||||
//check for line IRQ on first clock
|
||||
@ -223,6 +223,7 @@ bool ppuCycle()
|
||||
{
|
||||
//makes it possible to draw 160x144 in here :)
|
||||
size_t drawPos = (ppuDots)+(ppuLines*160);
|
||||
//heavy cpu load from this
|
||||
ppuDrawDot(drawPos);
|
||||
ppuDots++;
|
||||
}
|
||||
@ -286,7 +287,7 @@ ppuIncreasePos:
|
||||
//copy our line val into public reg
|
||||
PPU_Reg[4] = ppuLines;
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool ppuDrawDone()
|
||||
@ -439,7 +440,7 @@ void ppuDumpMem()
|
||||
FILE *f = fopen("PPU_VRAM.bin","wb");
|
||||
if(f)
|
||||
{
|
||||
fwrite(PPU_VRAM,1,allowCgbRegs?0x4000:0x2000,f);
|
||||
fwrite(PPU_VRAM,1,gbCgbMode?0x4000:0x2000,f);
|
||||
fclose(f);
|
||||
}
|
||||
f = fopen("PPU_OAM.bin","wb");
|
||||
@ -791,3 +792,98 @@ static void ppuDrawDotCGB(size_t drawPos)
|
||||
//copy color value from BGR32 LUT
|
||||
textureImage[drawPos] = PPU_CGB_BGRLUT[cgbRGB&0x7FFF];
|
||||
}
|
||||
|
||||
//64x12 1BPP "Track"
|
||||
static const uint8_t ppuGBSTextTrack[96] =
|
||||
{
|
||||
0x0C, 0x1C, 0x03, 0xD8, 0x7C, 0x71, 0xC0, 0x00, 0x0C, 0x1C, 0x07, 0xF8, 0xFE, 0x73, 0x80, 0x00,
|
||||
0x0C, 0x1C, 0x06, 0x39, 0xE2, 0x77, 0x00, 0x00, 0x0C, 0x1C, 0x07, 0x39, 0xC0, 0x7E, 0x00, 0x00,
|
||||
0x0C, 0x1C, 0x07, 0xF9, 0xC0, 0x7C, 0x00, 0x00, 0x0C, 0x1C, 0x01, 0xF9, 0xC0, 0x7C, 0x00, 0x00,
|
||||
0x0C, 0x1E, 0x60, 0x38, 0xE2, 0x7E, 0x00, 0x00, 0x0C, 0x1F, 0xE3, 0xF8, 0xFE, 0x77, 0x00, 0x00,
|
||||
0x0C, 0x1D, 0xC3, 0xF0, 0x3C, 0x73, 0xC0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
|
||||
0xFF, 0xC0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
|
||||
};
|
||||
|
||||
//128x12 1BPP "0123456789/"
|
||||
static const uint8_t ppuGbsTextRest[192] =
|
||||
{
|
||||
0x0E, 0x1F, 0xF7, 0xF8, 0xF8, 0x03, 0x9F, 0x01, 0xF0, 0x60, 0x1F, 0x0F, 0x83, 0x00, 0x00, 0x00,
|
||||
0x3F, 0x9F, 0xF7, 0xF9, 0xFC, 0x03, 0x9F, 0xC3, 0xF8, 0x70, 0x3F, 0x8F, 0xC3, 0x00, 0x00, 0x00,
|
||||
0x3B, 0x83, 0x83, 0x80, 0x0E, 0x7F, 0xC1, 0xE7, 0x1C, 0x70, 0x71, 0xC0, 0xE1, 0x80, 0x00, 0x00,
|
||||
0x71, 0xC3, 0x81, 0xC0, 0x0E, 0x7F, 0xC0, 0xE7, 0x1C, 0x30, 0x71, 0xC0, 0x71, 0x80, 0x00, 0x00,
|
||||
0x79, 0xC3, 0x80, 0xE0, 0x0E, 0x63, 0x80, 0xE7, 0x1C, 0x38, 0x71, 0xC7, 0x70, 0xC0, 0x00, 0x00,
|
||||
0x7D, 0xC3, 0x80, 0x70, 0x7E, 0x33, 0x81, 0xE7, 0x1C, 0x18, 0x3F, 0x8F, 0xF0, 0xC0, 0x00, 0x00,
|
||||
0x77, 0xC3, 0x80, 0x70, 0x7C, 0x13, 0x9F, 0xC7, 0xF8, 0x1C, 0x1F, 0x1C, 0x70, 0x60, 0x00, 0x00,
|
||||
0x73, 0xC3, 0x80, 0x38, 0x0E, 0x1B, 0x9F, 0x87, 0x70, 0x1C, 0x31, 0x9C, 0x70, 0x60, 0x00, 0x00,
|
||||
0x71, 0xC3, 0x80, 0x38, 0x0E, 0x0B, 0x9C, 0x07, 0x00, 0x0C, 0x71, 0xDC, 0x70, 0x30, 0x00, 0x00,
|
||||
0x3B, 0x9F, 0x80, 0x38, 0x0E, 0x0F, 0x9C, 0x03, 0x80, 0x0E, 0x71, 0xDC, 0x70, 0x30, 0x00, 0x00,
|
||||
0x3F, 0x8F, 0x83, 0xF1, 0xFC, 0x07, 0x9F, 0xC1, 0xF9, 0xFE, 0x3F, 0x8F, 0xE0, 0x18, 0x00, 0x00,
|
||||
0x0E, 0x03, 0x81, 0xE0, 0xF8, 0x03, 0x9F, 0xC0, 0xF9, 0xFE, 0x1F, 0x07, 0xC0, 0x18, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static void ppuDrawRest(uint8_t curX, uint8_t sym)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for(i = 0; i < 12; i++)
|
||||
{
|
||||
for(j = 0; j < 10; j++)
|
||||
{
|
||||
size_t drawPos = (j+curX)+((i+4)*160);
|
||||
uint8_t xSel = (j+(sym*10));
|
||||
if(ppuGbsTextRest[((11-i)<<4)+(xSel>>3)]&(0x80>>(xSel&7)))
|
||||
textureImage[drawPos] = 0xFFFFFFFF; //White
|
||||
else
|
||||
textureImage[drawPos] = 0xFF000000; //Black
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppuDrawGBSTrackNum(uint8_t cTrack, uint8_t trackTotal)
|
||||
{
|
||||
memset(textureImage,0,0x16800);
|
||||
uint8_t curX = 4;
|
||||
//draw "Track"
|
||||
uint8_t i, j;
|
||||
for(i = 0; i < 12; i++)
|
||||
{
|
||||
for(j = 0; j < 50; j++)
|
||||
{
|
||||
size_t drawPos = (j+curX)+((i+4)*160);
|
||||
if(ppuGBSTextTrack[((11-i)<<3)+(j>>3)]&(0x80>>(j&7)))
|
||||
textureImage[drawPos] = 0xFFFFFFFF; //White
|
||||
else
|
||||
textureImage[drawPos] = 0xFF000000; //Black
|
||||
}
|
||||
}
|
||||
//"Track" len+space
|
||||
curX+=60;
|
||||
//draw current num
|
||||
if(cTrack > 99)
|
||||
{
|
||||
ppuDrawRest(curX, (cTrack/100)%10);
|
||||
curX+=10;
|
||||
}
|
||||
if(cTrack > 9)
|
||||
{
|
||||
ppuDrawRest(curX, (cTrack/10)%10);
|
||||
curX+=10;
|
||||
}
|
||||
ppuDrawRest(curX, cTrack%10);
|
||||
curX+=10;
|
||||
//draw the "/"
|
||||
ppuDrawRest(curX, 10);
|
||||
curX+=10;
|
||||
//draw total num
|
||||
if(trackTotal > 99)
|
||||
{
|
||||
ppuDrawRest(curX, (trackTotal/100)%10);
|
||||
curX+=10;
|
||||
}
|
||||
if(trackTotal > 9)
|
||||
{
|
||||
ppuDrawRest(curX, (trackTotal/10)%10);
|
||||
curX+=10;
|
||||
}
|
||||
ppuDrawRest(curX, trackTotal%10);
|
||||
curX+=10;
|
||||
}
|
||||
|
3
ppu.h
3
ppu.h
@ -9,7 +9,7 @@
|
||||
#define _ppu_h_
|
||||
|
||||
void ppuInit();
|
||||
bool ppuCycle();
|
||||
void ppuCycle();
|
||||
bool ppuDrawDone();
|
||||
uint8_t ppuGetVRAMBank8(uint16_t addr);
|
||||
uint8_t ppuGetVRAMNoBank8(uint16_t addr);
|
||||
@ -22,5 +22,6 @@ void ppuSetReg8(uint16_t addr, uint8_t val);
|
||||
bool ppuInVBlank();
|
||||
bool ppuInHBlank();
|
||||
void ppuDumpMem();
|
||||
void ppuDrawGBSTrackNum(uint8_t cTrack, uint8_t trackTotal);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user