Last active
August 29, 2015 14:09
-
-
Save gucchan22/1b21a47ae3f3380223cc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <SDL2/SDL.h> | |
#define __DEBUG_FLAG__ 1 | |
class INESParser { | |
const char *rom_path; | |
uint8_t *prg_rom = NULL; | |
uint8_t *chr_rom = NULL; | |
unsigned int prg_rom_size, chr_rom_size, prg_rom_page, chr_rom_page; | |
bool vertical_mirroring, horizontal_mirroring; | |
bool mapper_no; // 0-fixed | |
enum MirroringType { vertical, horizontal }; | |
public: | |
explicit INESParser(const char *path) : rom_path(path) {} | |
~INESParser() { release(); } | |
void release() { | |
if(prg_rom) { | |
delete []prg_rom; | |
prg_rom = NULL; | |
} | |
if(chr_rom) { | |
delete []chr_rom; | |
chr_rom = NULL; | |
} | |
} | |
void parse() { | |
release(); | |
FILE *rom_ptr = fopen(rom_path, "rb"); | |
unsigned char signature[4], tmp_o, tmp_t; | |
fread(signature, 4, 1, rom_ptr); | |
if(memcmp(signature, "NES\x1A", 4) == 0) { | |
fread(&prg_rom_page, 1, 1, rom_ptr); | |
fread(&chr_rom_page, 1, 1, rom_ptr); | |
prg_rom_size = prg_rom_page * 0x4000; | |
chr_rom_size = chr_rom_page * 0x2000; | |
fread(&tmp_o, 1, 1, rom_ptr); // PPU Flag-0 | |
fread(&tmp_t, 1, 1, rom_ptr); // PPU Flag-1 | |
mapper_no = (tmp_o >> 4) | (tmp_t & 0xf0); | |
vertical_mirroring = (tmp_o & 1) == 1 ? true : false; | |
horizontal_mirroring = !vertical_mirroring; | |
prg_rom = new uint8_t[prg_rom_size]; | |
chr_rom = new uint8_t[chr_rom_size]; | |
fclose(rom_ptr); | |
//std::cout << "PRG:" << prg_rom_size << "Bytes, CHR:" << chr_rom_size << std::endl; | |
} | |
} | |
void inspect() { | |
std::cout << "ROM(*.nes) Information:\nMapper:0" << std::endl; | |
std::cout << "Mirroring:" << (this->getMirroringType() == vertical ? "Vertical" : "Horzontal") << std::endl; | |
std::cout << "PRG-ROM Size:" << (this->getPrgRomSize() / 1024) << "KB" << std::endl; | |
std::cout << "CHR-ROM Size:" << (this->getChrRomSize() / 1024) << "KB" << std::endl; | |
} | |
uint8_t *getPrgRom() { return prg_rom; } | |
uint8_t *getChrRom() { return chr_rom; } | |
MirroringType getMirroringType() { return this->vertical_mirroring ? vertical : horizontal; } | |
bool is_sram_enable() { return false; } | |
int mapper_number() { return mapper_no; } | |
unsigned int getPrgRomSize() { return prg_rom_size; } | |
unsigned int getChrRomSize() { return chr_rom_size; } | |
unsigned int getPrgRomPage() { return prg_rom_page; } | |
unsigned int getChrRomPage() { return chr_rom_page; } | |
}; | |
uint32_t rgb888[65] = { | |
0x6b6b6b, 0x001084, 0x08008c, 0x42007b, 0x63005a, 0x6b0010, 0x600000, 0x4f3500, | |
0x314e18, 0x005a21, 0x215a10, 0x085242, 0x003973, 0x000000, 0x000000, 0x000000, | |
0xa5a5a5, 0x0042c6, 0x4229ce, 0x6b00bd, 0x942994, 0x9c1042, 0x9c3900, 0x845e21, | |
0x5f7b21, 0x2d8c29, 0x188e10, 0x2e8663, 0x29739c, 0x000000, 0x000000, 0x000000, | |
0xefefef, 0x5a8cff, 0x7b6bff, 0xa55aff, 0xd64aff, 0xe7639c, 0xde7b52, 0xce9c29, | |
0xadb531, 0x7bce31, 0x5ace52, 0x4ac694, 0x4ab5ce, 0x525252, 0x000000, 0x000000, | |
0xefefef, 0xadc6ff, 0xbdbdff, 0xceb5ff, 0xe7b5ff, 0xf9bbdf, 0xf7c6b5, 0xdec69c, | |
0xd6d694, 0xc6e79c, 0xb5e7ad, 0xade7c6, 0xaddee7, 0xadadad, 0x000000, 0x000000 | |
}; | |
class RAM { | |
uint8_t ram_memory[0x800]; | |
public: | |
explicit RAM() {} | |
~RAM() {} | |
uint8_t read(uint16_t addr) const { return ram_memory[addr & 0x07ff]; } | |
void write(uint16_t addr, uint8_t v) { ram_memory[addr & 0x07ff] = v; } | |
}; | |
class VM { | |
RAM& ram; | |
public: | |
explicit VM(RAM &nes_ram, const std::string &rom_path) : ram(nes_ram) { | |
INESParser rom_parser = INESParser(rom_path.c_str()); | |
rom_parser.parse(); | |
} | |
~VM() {} | |
uint8_t read_u8(uint16_t addr) { | |
switch(addr & 0xf000) { | |
case 0x0000: return ram.read(addr); // RAM Read Access | |
} | |
return 0x0000; | |
} | |
uint16_t read_u16(uint16_t addr) { return (read_u8(addr) | (read_u8(addr + 1) << 8)); } | |
void write(uint16_t addr, uint8_t v) {} | |
}; | |
class RNESGraphics { | |
SDL_Window *window; | |
SDL_Renderer *renderer; | |
SDL_Texture *texture; | |
const char *window_title; | |
public: | |
explicit RNESGraphics(const std::string& wtitle) : window_title(wtitle.c_str()) { | |
SDL_CreateWindowAndRenderer(256, 240, 0, &window, &renderer); | |
SDL_SetWindowTitle(window, window_title); | |
SDL_RendererInfo info; | |
SDL_GetRendererInfo(renderer,&info); | |
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, 256, 240); | |
} | |
~RNESGraphics() { | |
SDL_DestroyTexture(texture); | |
SDL_DestroyRenderer(renderer); | |
SDL_DestroyWindow(window); | |
} | |
void executeRendering(uint8_t (&gbuff)[240][256], const uint8_t paletteMask) { | |
SDL_Event ev; | |
while(SDL_PollEvent(&ev)) { | |
if(ev.type == SDL_QUIT) exit(0); | |
} | |
uint32_t *line; | |
uint8_t *line8; | |
int pitch; | |
SDL_LockTexture(texture, NULL, reinterpret_cast<void**>(&line8), &pitch); | |
for(int y = 0; y < 240; y++) { | |
line = reinterpret_cast<uint32_t*>(line8); | |
for(int x = 0; x < 256; x++) line[x] = rgb888[gbuff[y][x] & paletteMask]; | |
line8 += pitch; | |
} | |
SDL_UnlockTexture(texture); | |
SDL_RenderClear(renderer); | |
SDL_Rect rect; | |
rect.x = 0; | |
rect.w = 256; | |
rect.h = 240; | |
SDL_RenderCopy(renderer, texture, &rect, NULL); | |
SDL_RenderPresent(renderer); | |
} | |
}; | |
class RNESController { | |
uint8_t keyState; | |
public: | |
explicit RNESController() : keyState(0) {} | |
~RNESController() {} | |
void onVblank() { | |
const uint8_t *keyBoardState = SDL_GetKeyboardState(NULL); | |
SDL_Scancode scancodes[] = { | |
SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, | |
SDL_SCANCODE_A, SDL_SCANCODE_B, SDL_SCANCODE_T, SDL_SCANCODE_S, | |
}; | |
for(int i = 0; i < 8; i++) { | |
if(keyBoardState[scancodes[i]]) keyState |= i; | |
} | |
} | |
bool isPressed(int index) { return ((keyState >> index) & 1) == 1; } | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment