NES Library
       2022-09-22
       Last edit: 2022-09-22
       ---------------------
       
       I wanted to learn more about how the NES works, so I consulted the resources on 
 (HTM) Nesdev Wiki
        and I discovered that from an NES program (`.nes` file) you could do cool stuff like extracting some tilesets from the CHR ROM (Character Read-Only Memory) or a PRNG (Pseudorandom Number Generator) with the instructions interpreted by the NES.
       
       ## CLI
       
       I made an example binary that can run all the main features of the `nes-utils` library to make it more convenient to test.
       
 (HTM) https://github.com/theobori/nes-utils-cli
       
       ## Tilesets dumping
       
       A NES program include a 16 bytes header, we can represent it like this:
       
       ```rust
       const NES_HEADER_FIELDS_ORDER: [(&str, usize, usize); 9] = {
           [
               ("magic", 0, 4),
               ("len_prg_rom", 4, 1),
               ("len_chr_rom", 5, 1),
               ("f6", 6, 1),
               ("f7", 7, 1),
               ("len_prg_ram", 8, 1),
               ("f9", 9, 1),
               ("f10", 10, 1),
               ("reserved", 11, 5)
           ]
       };
       ```
       
       In this example, the field magic is at position 0 and has a lenght of 4 bytes.
       
       The CHR ROM is linked to the PPU (Picture Process Unit), it means if the CHR ROM length is superior to zero, it contains some graphics.
       
       There are not all the tilesets of the game in the CHR, you can find `0x2000 * len_chr_rom` bytes in it, with two banks of `0x1000` bytes, which makes two images of 8 kilobytes, there is one bank for one image.
       
       So, let's take the example of `Kirby's Adventure`, below are the graphical data of the CHR rom:
       
       There are only four colors because the rest is calculated at runtime. Below are the main parts of code that generate this 2 images:
       
       ### Colors
       ```rust
       type Rgb = (u8, u8, u8);
       
       const BLACK_PIXEL: Rgb = (0, 0, 0);
       const COLOR_SCHEME: [Rgb; 4] = [
           (0, 0, 0),
           (126, 126, 126),
           (189, 189, 189),
           (255, 255, 255)
       ];
       
       fn bits_to_rgb(left: u8, right: u8) -> Rgb {
           let color = right << 1 | left;
       
           COLOR_SCHEME[color as usize]
       }
       ```
       
       ### Bytes to RGB
       ```rust
       pub fn fill_with_bank(&mut self, bank: &[u8]) {
           let mut mem_x = 0;
           let mut mem_y = 0;
       
           for byte in (0..bank.len()).step_by(16) {
               for y in 0..8 {
                   if mem_x >= NesImage::W {
                       mem_y += NesImage::TILE_H;
                       mem_x = 0;
                   }
       
                   let lower = bank[byte + y];
                   let upper = bank[byte + y + 8];
       
                   for bit in 0..8 {
                       let pixel = bits_to_rgb(
                           lower >> (7 - bit) & 1,
                           upper >> (7 - bit) & 1
                       );
                       self.put_pixel(bit + mem_x, y + mem_y, pixel);
                   }
               }
               mem_x += NesImage::TILE_W;
           }
       }
       ```
       
       ## Disassembling
       
       The bytecodes are in the PGR ROM (Program Read-Only Memory) of size `0x4000 * len_chr_rom` (value in the header) bytes.
       
       So, for `Kirby's Adventure`, the assembler code should looks like:
       
       ```asm6502
       ; Mapped registers
       
       SQ1_VOL equ $4000
       SQ1_SWEEP equ $4001
       PPUMASK equ $2001
       SQ1_LO equ $4002
       SQ1_HI equ $4003
       SQ2_SWEEP equ $4005
       ...
       
       ; Header
       
       hex 4e 45 53 1a
       hex 20
       hex 20
       hex 43
       hex 00
       hex 00
       hex 00
       hex 00
       hex 00 00 00 00 00
       
       ; PRG ROM
       
       and ($0f, x)      ; 21 0f
       slo $280f         ; 0f 0f 28
       slo $2121         ; 0f 21 21
       jsr $2020         ; 20 20 20
       jsr $0221         ; 20 21 02
       slo $200f         ; 0f 0f 20
       and ($0f, x)      ; 21 0f
       ...
       ```
       
       ## Game Genie code
       
       - *The Game Genie is a enhancement cart for the NES designed by Camerica and distributed by Galoob and Cameric*
       - *it provides a simple interface to enter up to three cheat codes*
       
       *Source: 
 (HTM) NesDev Wiki
       *
       
       Obviously I didn't buy the enhancement cart, so I can't use the available codes. But on some emulators it is possible to access the memory and inject values.
       
       So I made a feature that decodes the Game Genie codes.
       
       For example for `Kirby's Adventure`, it is possible to have infinite energy with the following code:
       
       ```text
       $ nes-utils-cli --code SZEPSVSE    
       Address 0x1e05
       Value 0xad
       Compare value 0x8d
       ```
       
       ## Links
       
 (HTM) https://github.com/theobori/nes-utils