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 @@ | |||
| 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 | } | ||
