emu_nes

An NES emulator for learning how the 6502 and similar computers of the era worked
Log | Files | Refs | README | LICENSE

rom.c (1312B)


      1 #include <stdint.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 #include "rom.h"
      7 
      8 void
      9 parse_rom(const uint8_t *data, size_t data_len, struct rom *rom)
     10 {
     11 	size_t prg_rom_offset = 16;
     12 	size_t chr_rom_offset = 0;
     13 
     14 	if (data_len < 16) {
     15 		fprintf(stderr, "Invalid ROM: size less than 16 bytes\n");
     16 		exit(1);
     17 	}
     18 
     19 	if (data[0] != 'N' || data[1] != 'E' || data[2] != 'S' || data[3] != 0x1A) {
     20 		fprintf(stderr, "Invalid ROM: not in iNES format\n");
     21 		exit(1);
     22 	}
     23 
     24 	/* trainer data present */
     25 	if (data[6] & (1 << 2))
     26 		prg_rom_offset += 512;
     27 
     28 	rom->prg_rom_size = data[4] * 0x4000;
     29 	rom->prg_rom = calloc(rom->prg_rom_size, 1);
     30 	memcpy(rom->prg_rom, data + prg_rom_offset, rom->prg_rom_size);
     31 
     32 	rom->chr_rom_size = data[5] * 0x2000;
     33 	if (rom->chr_rom_size > 0) {
     34 		rom->chr_rom = calloc(rom->chr_rom_size, 1);
     35 		chr_rom_offset = prg_rom_offset + rom->prg_rom_size;
     36 		memcpy(rom->chr_rom, data + chr_rom_offset, rom->chr_rom_size);
     37 	}
     38 
     39 	if ((data[6] & (1 << 3)) != 0)
     40 		rom->mirror = M_FOUR;
     41 	else if ((data[6] & 1) == 1)
     42 		rom->mirror = M_VERTICAL;
     43 	else if ((data[6] & 1) == 0)
     44 		rom->mirror = M_HORIZONTAL;
     45 
     46 	rom->mapper = (data[6] & (0xF << 4)) >> 4;
     47 	rom->mapper |= data[7] & (0xF << 4);
     48 }
     49 
     50 void
     51 free_rom(struct rom *rom)
     52 {
     53 	free(rom->prg_rom);
     54 	if (rom->chr_rom_size > 0)
     55 		free(rom->chr_rom);
     56 }