LoadNESFile reads an iNES file (.nes) and returns a Cartridge on success. http://wiki.nesdev.com/w/index.php/INES http://nesdev.com/NESDoc.pdf (page 28)
(path string)
| 23 | // http://wiki.nesdev.com/w/index.php/INES |
| 24 | // http://nesdev.com/NESDoc.pdf (page 28) |
| 25 | func LoadNESFile(path string) (*Cartridge, error) { |
| 26 | // open file |
| 27 | file, err := os.Open(path) |
| 28 | if err != nil { |
| 29 | return nil, err |
| 30 | } |
| 31 | defer file.Close() |
| 32 | |
| 33 | // read file header |
| 34 | header := iNESFileHeader{} |
| 35 | if err := binary.Read(file, binary.LittleEndian, &header); err != nil { |
| 36 | return nil, err |
| 37 | } |
| 38 | |
| 39 | // verify header magic number |
| 40 | if header.Magic != iNESFileMagic { |
| 41 | return nil, errors.New("invalid .nes file") |
| 42 | } |
| 43 | |
| 44 | // mapper type |
| 45 | mapper1 := header.Control1 >> 4 |
| 46 | mapper2 := header.Control2 >> 4 |
| 47 | mapper := mapper1 | mapper2<<4 |
| 48 | |
| 49 | // mirroring type |
| 50 | mirror1 := header.Control1 & 1 |
| 51 | mirror2 := (header.Control1 >> 3) & 1 |
| 52 | mirror := mirror1 | mirror2<<1 |
| 53 | |
| 54 | // battery-backed RAM |
| 55 | battery := (header.Control1 >> 1) & 1 |
| 56 | |
| 57 | // read trainer if present (unused) |
| 58 | if header.Control1&4 == 4 { |
| 59 | trainer := make([]byte, 512) |
| 60 | if _, err := io.ReadFull(file, trainer); err != nil { |
| 61 | return nil, err |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | // read prg-rom bank(s) |
| 66 | prg := make([]byte, int(header.NumPRG)*16384) |
| 67 | if _, err := io.ReadFull(file, prg); err != nil { |
| 68 | return nil, err |
| 69 | } |
| 70 | |
| 71 | // read chr-rom bank(s) |
| 72 | chr := make([]byte, int(header.NumCHR)*8192) |
| 73 | if _, err := io.ReadFull(file, chr); err != nil { |
| 74 | return nil, err |
| 75 | } |
| 76 | |
| 77 | // provide chr-rom/ram if not in file |
| 78 | if header.NumCHR == 0 { |
| 79 | chr = make([]byte, 8192) |
| 80 | } |
| 81 | |
| 82 | // success |
no test coverage detected