diff options
author | vin <git@vineetk.net> | 2024-06-17 14:46:00 +0530 |
---|---|---|
committer | vin <git@vineetk.net> | 2024-06-17 14:46:46 +0530 |
commit | 77d37dd455f804c79969979eb39d525b3c5ddfe7 (patch) | |
tree | 5cc5ba7972615cdc473f6897a80348c255725c6a /rom.c | |
parent | 1f6e3b054cd7a35c5eb8d908525a261ea83d44e7 (diff) |
implement basic iNES and Mapper 0 ROM loading
It seems like the test ROM loads fine but the instructions are not,
but that's exactly what the test ROM is for I suppose.
Diffstat (limited to 'rom.c')
-rw-r--r-- | rom.c | 56 |
1 files changed, 56 insertions, 0 deletions
@@ -0,0 +1,56 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "rom.h" + +void +parse_rom(const uint8_t *data, size_t data_len, struct Rom *rom) +{ + size_t prg_rom_offset = 16; + size_t chr_rom_offset = 0; + + if (data_len < 16) { + fprintf(stderr, "Invalid ROM: size less than 16 bytes\n"); + exit(1); + } + + if (data[0] != 'N' || data[1] != 'E' || data[2] != 'S' || data[3] != 0x1A) { + fprintf(stderr, "Invalid ROM: not in iNES format\n"); + exit(1); + } + + /* trainer data present */ + if (data[6] & (1 << 2)) + prg_rom_offset += 512; + + rom->prg_rom_size = data[4] * 0x4000; + rom->prg_rom = calloc(rom->prg_rom_size, 1); + memcpy(rom->prg_rom, data + prg_rom_offset, rom->prg_rom_size); + + rom->chr_rom_size = data[5] * 0x2000; + if (rom->chr_rom_size > 0) { + rom->chr_rom = calloc(rom->chr_rom_size, 1); + chr_rom_offset = prg_rom_offset + rom->prg_rom_size; + memcpy(rom->chr_rom, data + chr_rom_offset, rom->chr_rom_size); + } + + if ((data[6] & (1 << 3)) != 0) + rom->mirror = M_FOUR; + else if ((data[6] & 1) == 1) + rom->mirror = M_VERTICAL; + else if ((data[6] & 1) == 0) + rom->mirror = M_HORIZONTAL; + + rom->mapper = (data[6] & (0xF << 4)) >> 4; + rom->mapper |= data[7] & (0xF << 4); +} + +void +free_rom(struct Rom *rom) +{ + free(rom->prg_rom); + if (rom->chr_rom_size > 0) + free(rom->chr_rom); +} |