Skip to content

qalle2/nes-pride

Repository files navigation

Qalle's Pride Flag Show II

Browse 71 pride flags on the NES. This program can also be downloaded from Itch.io.

screenshot screenshot screenshot

Table of contents:

List of files

Assembled NES programs (gzip compressed, from newest to oldest):

  • pride.nes.gz: current version (download this if you're unsure)
  • pride-compo-2023.nes.gz: NESDev Compo 2023 version
  • pride-nrom.nes.gz: the last NROM version
  • pride-compo-2022.nes.gz: NESDev Compo 2022 version

Images:

  • img/*.png: pride flags to be read by convert.py (256×192 pixels)
  • img-lq/*.png: lower-quality backups of some flags
  • chr-spr.png: sprite pattern table data; can be encoded using nes_chr_encode.py from my NES utilities
  • snap*.png: screenshots

Source code:

  • convert.py: a Python program that converts images of pride flags into NES graphics data; generates imgdata.asm and chr-bg*.bin
  • pride.asm: an NES program that shows the flags; assembles with ASM6
  • imgdata.asm: data used by pride.asm (generated by convert.py)
  • assemble.sh: a Linux script that assembles pride.asm (overwrites files; don't run it before reading it)

Other binaries (gzip compressed):

  • chr-bin.tar.gz: pattern table (CHR ROM) data in NES format; contains these files:
    • chr-bg*.bin: background (one file per PT; see convert.py above)
    • chr-spr.bin: sprites (same data in PTs 1/3/5/7; see chr-spr.png above)

How to assemble

  • run convert.py to generate imgdata.asm and chr-bg*.bin (or just download them and extract the .gz files)
  • encode chr-spr.png into chr-spr.bin using nes_chr_encode.py from my NES utilities (or just extract chr-spr.bin from the .gz file)
  • assemble: asm6 pride.asm pride.nes (or just extract pride.nes from the .gz file)

How to use the NES program

  • left arrow: previous flag
  • right arrow: next flag
  • A button: random flag
  • start button: toggle flag descriptions on or off

How to add new flags

You can add flags of your own to the NES program. You need to have Python and ASM6 installed.

  1. Open your flag image in an image editor (e.g. GNU IMP).
  2. Resize the image to 256×192 pixels.
  3. Convert the image into indexed color (so it has a palette).
  4. Because of NES hardware limitations, the colors need to be optimized manually and the pixels may need to be edited as well. This is tricky, but follow these rules:
    • No more than 12 unique colors in addition to black.
    • All unique colors should be clearly distinct from each other.
    • Put a 16×16-pixel grid on the image (in GNU IMP, Image → Configure Grid… and View → Show Grid).
    • No grid square can have more than three distinct colors in addition to black.
    • In all grid squares combined, you can't use more than four unique sets of three distinct colors in addition to black.
  5. Save the image in PNG format under the img directory. The filename before the extension (.png) is important:
    • It will be the flag description text (up to 8×3 characters) inside the NES program.
    • 26 characters or less.
    • Only az, 09, comma (,), hyphen (-) and underscore (_) are allowed.
    • Underscores will be converted into newlines.
    • No more than two underscores.
    • No more than eight consecutive non-underscore characters.
    • See the existing filenames for examples.
  6. Run python3 convert.py. It should not print any errors. However, the palette creation algorithm isn't very smart, so if you're sure you followed step 4 correctly and the program still complains, you can define the palette manually: edit MANUAL_SUBPALS in convert.py. The output just before the error message and NES_PALETTE in convert.py will be helpful.
  7. Extract chr-spr.bin from the .gz file. (Use e.g. gunzip on Linux or 7-Zip on Windows.)
  8. Assemble: asm6 pride.asm pride.nes – again, it should not print any errors.
  9. Run pride.nes on an NES emulator (e.g. FCEUX, Nestopia, Mednafen).

Technical info on the NES program

  • mapper: CNROM (iNES mapper #3)
  • PRG ROM: 16 KiB
  • CHR ROM: 32 KiB
  • name table mirroring: vertical
  • pattern table 0 in each bank: background (flag images)
  • pattern table 1 in each bank – first 208 tiles: background (flag images)
  • pattern table 1 in each bank – last 48 tiles: sprites (flag descriptions; same in all banks)
  • each image has its own background palettes (black and 4×3 other colors)
  • flag images are 256×192 pixels (32×24 tiles or 16×12 attribute blocks)
  • flag images are shown at the bottom of a name/attribute table
  • name/attribute table data of each flag image:
    • uncompressed size: 24×32 + 8×8 = 832 bytes
    • stored as 6 run-length encoded slices; the first 5 decompress into 140 bytes each, the last into 132 bytes
  • an image is updated during 7 frames:
    • first 6 frames: extract one slice of name/attribute table data to an invisible name/attribute table
    • 7th frame: copy background palettes, do OAM DMA, flip visible name/attribute table, switch to correct CHR bank and background pattern table
    • for speed, all PPU memory updates (VRAM/palette) go through a buffer on the stack page (can be read quickly with PLA)

Sources of flags

The license of this project does not apply to the flag images (I guess).