Created
June 16, 2019 05:30
-
-
Save justinmeiners/23951d31501ada97a9e0b4676d6fc01b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* Created By: Justin Meiners (2012) | |
This is the only worthwhile piece a project I wrote in 2012. I got interested in emulation after watching | |
[Bisqwit's video](https://www.youtube.com/watch?v=y71lli8MS8s) | |
It was interesting to learn about how the cartridge data is organized | |
and how the graphics are stored. | |
I didn't get very far into the actual emulation, as the CPU has tons of instructions | |
with slightly different variations and I didn't understand computer architecture at the time. | |
Bisqwit's method is the best I have seen for handling the tedious instructions. I didn't use C++ | |
so I attempted to combine logical parts with a set of macros. | |
Resources: | |
http://fms.komkon.org/EMUL8/HOWTO.html#LABH | |
http://www.z80.info | |
http://en.wikipedia.org/wiki/Picture_Processing_Unit | |
http://sadistech.com/nesromtool/romdoc.html | |
http://nesdev.icequake.net/NES%20emulation%20discussion.txt | |
http://opcode-defined.quora.com/How-NES-Graphics-Work-Sprites-and-Palettes | |
http://www.atarimax.com/jindroush.atari.org/aopc.html#BRK | |
http://www.thealmightyguru.com/Games/Hacking/Wiki/index.php?title=6502_Opcodes | |
http://wiki.nesdev.com/w/index.php/NMI | |
*/ | |
/* 16 kb */ | |
#define ROM_BANK_SIZE 16384 | |
/* 8 kb */ | |
#define VROM_BANK_SIZE 8192 | |
/* 2 kb */ | |
#define RAM_SIZE 2048 | |
ypedef struct | |
{ | |
u8 romBankCount; /* prg */ | |
u8 vromBankCount; /* char */ | |
u8* ROM; | |
u8* VROM; | |
} GamePack_t; | |
void GamePack_InitWithFile(GamePack_t* pack, const char* path) | |
{ | |
FILE* file = fopen(path, "rb"); | |
/* header NES 16 bytes */ | |
assert(fgetc(file) == 'N'); | |
assert(fgetc(file) == 'E'); | |
assert(fgetc(file) == 'S'); | |
assert(fgetc(file) == '\32'); | |
/* how many banks of ROM and VROM in cartridge? */ | |
pack->romBankCount = fgetc(file); | |
pack->vromBankCount = fgetc(file); | |
fseek(file, 10, SEEK_CUR); | |
/* allocate and read ROM and VROM */ | |
pack->ROM = malloc(pack->romBankCount * ROM_BANK_SIZE); | |
pack->VROM = malloc(pack->vromBankCount * VROM_BANK_SIZE); | |
fread(pack->ROM, ROM_BANK_SIZE, pack->romBankCount, file); | |
fread(pack->VROM, VROM_BANK_SIZE, pack->vromBankCount, file); | |
fclose(file); | |
} | |
// the images this spat out hand incorrect colors | |
// because they are depdendant on the color pallete | |
// which is set dynamically. | |
// It is still fun to extract the sprites form a ROM yourself! | |
typedef struct | |
{ | |
u8 r; | |
u8 g; | |
u8 b; | |
u8 a; | |
} Pix_t; | |
void GamePack_VROMDump(GamePack_t* pack) | |
{ | |
char header[18]={0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
header[12] = 8 & 0xFF; | |
header[13] = (8 >> 8) & 0xFF; | |
header[14] = (8) & 0xFF; | |
header[15] = (8 >> 8) & 0xFF; | |
header[16] = 32; | |
char bgPallete[3]; | |
bgPallete[0] = pack->VROM[0x3f00]; | |
bgPallete[1] = pack->VROM[0x3f01]; | |
bgPallete[2] = pack->VROM[0x3f02]; | |
char spritePallete[3]; | |
spritePallete[0] = pack->VROM[0x3f11]; | |
spritePallete[1] = pack->VROM[0x3f12]; | |
spritePallete[2] = pack->VROM[0x3f13]; | |
int i = 0; | |
int vc = 0; | |
for (i = 0; i < (VROM_BANK_SIZE / 16); i ++) | |
{ | |
char file[128]; | |
sprintf(file, "spr_%i.tga", i); | |
FILE* f = fopen(file, "wb"); | |
fwrite(header, sizeof(header), 1, f); | |
u8* channel1 = pack->VROM + vc; | |
vc += 8; | |
u8* channel2 = pack->VROM + vc; | |
vc += 8; | |
Pix_t sprite[64]; | |
int x; | |
int y; | |
for (y = 0; y < 8; y ++) | |
{ | |
for (x = 0; x < 8; x ++) | |
{ | |
int ind = (7 - x) * 8 + (7 - y); | |
u8 chan1Val = (channel1[x] & (1 << y)) != 0; | |
u8 chan2Val = (channel2[x] & (1 << y)) != 0; | |
u8 pixValue = chan1Val | (chan2Val << 1); | |
sprite[ind].r = (pixValue == 1) * 255; | |
sprite[ind].g = (pixValue == 2) * 255; | |
sprite[ind].b = (pixValue == 3) * 255; | |
sprite[ind].a = (pixValue != 0) * 255; | |
} | |
} | |
fwrite(sprite, 8 * 8, sizeof(Pix_t), f); | |
fclose(f); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment