Jump to content
  • entries
    39
  • comments
    0
  • views
    834

Screen Compression Evolution


Piledriver

40 views

I got a bunch of questions about how I made 1024 screens for Oh Shoot!  I hope this answers those questions.

 

There were several iterations to my level storage solutions.

 

1.  Naïve level storage
-store PF0, PF1, and PF2 for each of the 22 rows of a screen (66 bytes per screen - no compression)
-screen drawn directly from ROM
-I think this only allowed me 4 screens in my 4KB game?  Don't remember.

 

2.  Run length encoding
-used 4 unused bits in PF0 to store run length value
-identical adjacent rows now grouped into chunks
-run length data extracted on the fly in the kernel code (not ideal but it worked)
-allowed me to have 16 screens in my 4KB game

 

3.  Screens are a list of indexes into a chunk palette
-each index is one byte (can index up to 256 chunks... although I only had space for much fewer chunks)
-chunks can be reused many times and in different screens
-each screen is between 2 and 15 indexes to chunks (limiting the number of times I can change the playfield values to 15 times per screen)
-each chunk palette entry consists of PF1 and PF2 data (I ditched PF0) and the run length encoding value (number of rows in the chunk)
-this data could no longer be decompressed on the fly
-needed 22 rows x 2PF bytes of RAM for my uncompressed screen that could be easily drawn
-44 bytes of RAM required!!!
-I also needed one frame between rounds to load/decompress the screen into RAM
-In my 4KB game I only had about 640 bytes for all my screens
-I was able to make 64 screens that were mostly big chunky blocks.

 

4.  Chunk Palettes with bank switching (32KB)
-Instead of using the leftover crumbs in my 4KB game for level data I now had 4 banks just for level data (and decompression/retrieval code) - that's half the ROM right there!
-Instead of one set of 64 screens (lists of chunk indexes) and corresponding chunk palettes I now had 16 sets of 64 screens each with corresponding chunk palette for each screen set.
-Not only did I now have 16 sets of screens instead of only 1, but each set was almost a full KB instead of only 640 bytes.
-16 sets of 64 screens each = 1024 screens!


*storing each row uncompressed in RAM and having lots of ROM to play with made it relatively easy to add warping effects
*there is no metadata stored for a screen... screens have to be analyzed to generate metadata like where the corridors are for AI and greatest corridor width to determine if warp effect can be applied
*the analysis also cuts the screen in two vertically so the vertical scrolling makes sense (we wouldn't want a castle to be cut in half during scroll in effect for example)

 

I could not manually generate the screen set data, so I wrote a C# app to automate this process.  For each set it reads in 64 pngs - one for each screen and generates the screen set from that.  This app also generates reports on how much rom the screen set uses, how many chunks there are, how often the chunks are used in the screen set, which screens they appear in, etc.  This would allow me to edit my screens while staying inside my byte budget.

 

Creating/editing screens was my fun task that I would keep coming back to when frustrated with coding.

 

There are even more details than this, but I think this gives you a good idea of what was involved.

Edited by Piledriver

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...