The mini-series about Faxanadu level data is slowly coming to an end. Today's update might be the second-to-last part of the series if I counted correctly. In this update I'm going to explain how to find the correct palette for a given screen. In one of the last updates I had already hinted that choosing the proper palette for a screen is an inductive process, the color palette used in screen N depends on the color palette used in screen N-1 and some other information.
Of course it all begins with the first screen, the one where the game starts right outside the first town. This screen uses the palette with palette ID 0. The accompanying code that initializes the first level can be found in the subroutine from offset $DEA7 - $DEF2. Here are the most important parts of the code.
CODE:
$DEA7-> A9 00: LDA #$00
<br />$DEA9-> 85 24: STA $24
<br />...
<br />$DEDF-> A6 24: LDX $24
<br />$DEE1-> BD 4C DF: LDA $DF4C,X
<br />$DEE4-> 85 65: STA $65
In the first two instructions the current level is set to 0, in the last three instructions the current level is used as an index into a table which holds the palettes used in the first screen of every level. The first screen is not necessarily the screen with ID 0 however, it's just the screen where the level begins.
This palette ID table can be found at offset 0x3DF5C. It's 8 bytes long (one palette for each level chunk) and contains the values {0x00, 0x06, 0x0A, 0x1B, 0x1B, 0x08, 0x0C, 0x0F}.
The palette ID itself is used as an index into the actual palette table which can be found between the offsets 0x2C010 and 0x2C1F0. As each palette entry is 0x10 bytes large (= 0x10 colors per palette) this table contains 31 different palettes.
Now that the start of the inductive process has been found it's time to go through the possible palette changes. All possibilities of a palette change were already briefly mentioned in former updates. Here they are again:
- Regular scrolling
- Scrolling with a palette change (2 different ways)
- Walking through doors (without a level change)
- Walking through doors (Entering a building)
- Walking through doors (with a level change)
The first method, regular scrolling, is the most simple method. When a room Y is entered from a room X and the information used for that screen change can be found in the regular scrolling data the palette won't change. The palette of room Y is the palette of room X.
As mentioned in the last update there are also two ways to scroll between screens that can change the palette. Both of these ways are performed with the help of meta-data tables which contain one byte per entry that holds the new palette ID.
When entering a regular door that leads into another part of the current level the new palette ID can be found in the 2nd byte of the door destination table entry of the door. This value is loaded by the instruction at offset $EA45.
When entering a building another special table can be found that contains the palette IDs of the individual buildings. This palette can be found at offset 0x3E619, it's accessed from code at offset 0xE581. Curiously the 10 different buildings also have 10 different palettes, specifically the palettes with the IDs 0x11 to 0x1A.
The last way to force a palette change is to walk through a door to advance (or go back) one level. The table from offset 0x3DF5C comes into play again. This time however it's accessed by the code at offset $DF24, the subroutine that's used to load new levels when the player enters them.
I think this is a relatively complete overview of how to find the correct palette for any given screen. It's at least sufficient to draw the original Faxanadu screens in my level editor. Some questions remain though. I guess it's easily possible to give one room several different palettes depending from where the room was entered. The game shouldn't have any problem with that. How to handle such a situation in a level editor remains to be seen for now.