130 lines
2.6 KiB
C
130 lines
2.6 KiB
C
#include<assert.h>
|
|
#include<inttypes.h>
|
|
#include<stdbool.h>
|
|
#include<stdio.h>
|
|
#include<stdlib.h>
|
|
#include<string.h>
|
|
#include<time.h>
|
|
#include"cpu.h"
|
|
#include"ppu.h"
|
|
#include"gb.h"
|
|
|
|
#define _min(x,y) (((x)<(y))?(x):(y))
|
|
#define _max(x,y) (((x)>(y))?(x):(y))
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
FILE *romfile;
|
|
Gb gb;
|
|
bool hexdumponly=false;
|
|
char*fname=NULL;
|
|
|
|
// Allocate Gb state
|
|
gb=gb_new();
|
|
if(!gb.cpu||!gb.ppu||!gb.ram)goto quit;
|
|
gb.log=true;
|
|
|
|
// Parse arguments
|
|
for(size_t i=1;i<(size_t)argc;++i)
|
|
{
|
|
|
|
if(strcmp(argv[i],"-d")==0)
|
|
hexdumponly=true;
|
|
|
|
// Default action: treat as ROM file name
|
|
else
|
|
fname=argv[i];
|
|
|
|
}
|
|
|
|
// Try to open ROM file
|
|
if(fname)
|
|
{
|
|
romfile=fopen(argv[1],"rb");
|
|
if(!romfile)
|
|
{
|
|
fprintf(stderr,"error: failed to open file '%s'\n",argv[1]);
|
|
goto quit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"error: no ROM files specified\n");
|
|
goto quit;
|
|
}
|
|
|
|
// Allocate memory for entire ROM file
|
|
fseek(romfile,0,SEEK_END);
|
|
gb.romsize=ftell(romfile);
|
|
gb.romsize=_max(gb.romsize,0x8000);
|
|
gb.rom=malloc(gb.romsize);
|
|
if(!gb.rom)return 2;
|
|
|
|
// Map ROM file into memory
|
|
rewind(romfile);
|
|
fread(gb.rom,1,gb.romsize,romfile);
|
|
printf("Loaded ROM \'%s\' (%u B)\n",argv[1],gb.romsize);
|
|
printf("ROM Size: %ukB\n",32<<gb.rom[0x148]);
|
|
printf("RAM Size: %ukB\n",16<<gb.rom[0x149]*2);
|
|
fclose(romfile);
|
|
|
|
// Hex dump only
|
|
if(hexdumponly)
|
|
{
|
|
cpu_romhexdump(gb.rom);
|
|
goto quit;
|
|
}
|
|
|
|
// Load program into RAM
|
|
for(int i=0;i<0x8000;i++)
|
|
{
|
|
gb.ram[i]=gb.rom[i];
|
|
assert(gb.ram[i]==gb.rom[i]);
|
|
}
|
|
printf("Loaded 8000h (32768) bytes into RAM\n");
|
|
|
|
// Open window
|
|
if(gb.video)
|
|
ppu_openwindow(gb.ppu,gb.rom+0x134);
|
|
|
|
// VRAM bank
|
|
gb.ram[0xff4f]=0;
|
|
|
|
// Main CPU loop
|
|
for(;;)
|
|
{
|
|
if(gb.video)
|
|
if(ppu_updatewindow(&gb,gb.ram))break;
|
|
if(gb.paused)continue;
|
|
|
|
// Manage Control Registers
|
|
gb.ram[0xff44]+=1; // CURLINE (VBLANK INT AT:144-153)
|
|
//gb.ram[0xff05]+=1; // TIMA (TIMER INT AT OVERFLOW)
|
|
//if(!gb.ram[0xff05])gb.ram[0xff05]=gb.ram[0xff06];
|
|
gb.ram[0xff41]=(gb.ram[0xff41]+1)%4; // V-BLANK
|
|
|
|
// Handle Interrupts
|
|
//if(gb.ram[0xff44]==144 && gb.ram[0xffff] && gb.cpu->ime) // V-BLANK INT
|
|
//{
|
|
//gb.cpu->sp-=2; // Push pc, jump to 0040h interrupt
|
|
//cpu_write_ram(gb.cpu,gb.ppu,gb.cpu->sp,gb.cpu->pc&0x00ff,gb.ram);
|
|
//cpu_write_ram(gb.cpu,gb.ppu,gb.cpu->sp+1,gb.cpu->pc>>8,gb.ram);
|
|
//gb.cpu->pc=0x0040;
|
|
//}
|
|
|
|
/* if(gb.log) */
|
|
/* printf("\n[%#10.8x]%#5.2x: ",gb.cpu->pc,gb.rom[gb.cpu->pc]); */
|
|
|
|
// Fetch, decode, execute instruction
|
|
cpu_fetch8(gb.cpu,gb.rom,&gb.op);
|
|
cpu_decexec(gb.cpu,gb.ppu,gb.rom,&gb.op,gb.ram,!gb.log);
|
|
}
|
|
|
|
// Clean up, exit
|
|
quit:
|
|
gb_print_cpu_state(&gb);
|
|
if(gb.video)
|
|
ppu_closewindow(gb.ppu);
|
|
gb_free(&gb);
|
|
}
|