Skip to content

Instantly share code, notes, and snippets.

@freem
Last active December 5, 2019 05:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save freem/e0e88ed0d0c6d85bc1a95a404f28da45 to your computer and use it in GitHub Desktop.
Save freem/e0e88ed0d0c6d85bc1a95a404f28da45 to your computer and use it in GitHub Desktop.
simcity snes notes by lytron

sources:

r.i.p. to these files:

part 1:

  • The Game-Map is in WRAM at $7F0200.

  • Each tile is 16 bit in size (Seems like the data gets transfered from there to VRAM without any changes).

    • $00 00 is empty ground.
    • $01 00 is water
    • $02 00 is water
    • $03 00 is water
    • $04 00 is a shore (south-west to north-east, north-west is land)
    • $05 00 is a shore (east west, north is land)
    • $06 00 is a shore (south-east to north-west, north-east is land)
    • $07 00 is a shore (north south, west is land)
    • $08 00 is a shore (north south, east is land)
    • $09 00 is a shore (south-west to north-east, south-west is land)
    • $0A 00 to $13 00 are shores, too. Don't care for that
    • $14 00 to $25 00 are forest tiles
    • $26 00 is park (meadow)
    • $27 00 is park (tree)
    • $28 00 is a polluted area
    • $29 00 is a polluted area
    • $2A 00 to $2D 00 look like animation sprites of a explosion
    • $2E 00 and $2F 00 are... totally weird
    • From $30 00 on, you can find the street tiles
    • $70 00 are underwater rails (east west)
    • $71 00 are underwater rails (north south)
    • $72 00 are rails (east-west)
    • $76 00 are rails (east-south)
  • AWESOME! Residental areas without power supply have the tiles $80 00 81 00 82 00. Those WITH power supply have the tiles: $80 80 81 80 82 80. THIS IS WRONG I'LL EXPLAIN LATER Seems like the Data is edited somehow before it is transfered to VRAM. That bit that is used is originally for the Vertical Flip of the tile.

  • The Scenario Maps are compressed, of course.

    • Somehow the data is transfered from $7E8000 to $7F0200, there it gets decompressed to $7E8000, and gets (unchanged) transfered back to $7F0200.

    • The code for the decompression that happens from $7F0200 back to $7E8000 is at $03D1C4. #$FFFF is the signal for the end of data. Bits 10 to 13 (#$3C00) are the number of times this tile shall be repeated plus one (#%...0001... = #$0400 = two times the same tile; #%...1111... = #$3C00 = sixteen times the same tile)

    • The Data that is AT FIRST at $7E8000 is the data that gets decompressed as explained above. That data itself gets decompressed when it gets transfered from ROM to $7E8000.

    • #$FF is a special command in this data, I expect it to be the end signal of data.

    • Bits 5 to 7 are reserved for different commands.

    • If Bits 5 to 7 are #%000?.???? (= #$0? or #$1?), the following bytes get transfered directly to the decompressed data buffer as they are. The number of bytes that follow are Bits 0 to 4, minus one. For example: $01 $4F $50 sets two bytes, $4F and $50, directly in the buffer. $04 $02 $01 $40 $41 $24 sets the last five bytes in the buffer.

    • If Bits 5 to 7 are #%010?.???? (= #$4? or #$5?), the other bits are the number of bytes that get set in the following pattern (#$40 = one byte, #$41 = two bytes, #$50 = seventeen bytes etc.). The next two bytes are the pattern that get set. For Example: At the beginning of the San Fransisco Scenario Data, it is $4A $01 $3C. So the next eleven bytes (eleven = #$0B = #$0A + 1) are $01 $3C $01 $3c $01 $3C $01 $3c $01 $3C $01. That means, with an even number in the first byte, you decompress an uneven number of bytes, which means that the last 16-bit-data value isn't completed yet. The "$01 $3C" gets further decompressed to: "Repeat tile #$01 sixteen times". The last entry here has no number of repitions yet (the #$3C means the "repeat sixteen times"). Tile $01 is water, this is a whole lot of it. How... fitting for the border of a map.

    • If Bits 5 to 7 are #%110?.???? (= #$C? or #$D?), the program repeats some bytes that are already decompressed. The other bits contain the number of bytes that should be repeated minus one (so $C0 repeats one byte, $C3 repeats four bytes, $C4 repeats five bytes and so on). The next byte says how many bytes the thing should move back. So, if the last bytes were $04 $02 $C2 $03 and the next command is $C2 $03, the next bytes are $02 $C2 $03. If the next command is $C4 $02, the next bytes are $C2 $03 $C2 $03 $C2. The thing repeats the bytes itself set two loops ago. You get the idea.

    • Sim City uses the COP-Interrupt. Like Illusion of Gaia. Unlike Illusion of Gaia, it doesn't use the argument byte after the COP. Instead, it uses the value in A as an Index for a Jump Table.

    • The first decompression subroutine is one of the subroutines in the COP Jump Table. To start it, they load #$08 in A before they COP. If found out by accident that this decompression subroutine is often used on the title screen, too.

    • The Address Table for the Scenario Maps is at $03:CE70 onwards. Its not listed in whole 24-bit-values, but each byte is separated: Address Low Byte at $CE70+Y; Address High Byte at $CE79+Y and Address Bank at $CE82+Y.

First Decompression Commands, Part 2:

  • If Bits 5 to 7 are #%001?.???? (= #$2? or #$3?), the subroutine repeats the following byte multiple times. The number of repition is the value in Bits 0 to 4 plus one. E. g.: $22 $15 results in $15 $15 $15.
  • If Bits 5 to 7 are #%011?.???? (= #$6? or #$7?), the subroutine puts out a line of bytes that are counted up. The Argument Byte is the start value. E. g.: $64 $4A results in $4A $4B $4C $4D $4E.
  • If Bits 5 to 7 are #%100?.???? (= #$8? or #$9?), it seems like it is another of these repition things, but with absolute addressing instead of the relative addressing at #%110?.????.
  • I don't know what $A0 does, but it seems like it's for a horizontal repition of a vertical tile series. Not sure, don't interested in checking it (right now).

Other notes:

  • The game maps are 120 x 100 tiles in size.
  • At the end of each scenario data, they write an $FF $FF $FF. A single, well-placed $FF should have done it, too.
  • The game won't break if the compressed map data isn't enough to fill the whole screen. I tested it by completely removing one scenario map, directing straight on a $FF $FF $FF. The game started to run, the map was a mess, of course, because it interpreted every junk that was left in WRAM as map data. Unfortunately, there were some weird things that happened, so you can possibly crash your game if you play it that way.
  • The road tiles are at $30-$3F. $40-$4F and $50-5F are the very same tiles, but crowded and super-crowded. If you place them by WRAM editing, they soon turn normal if there is nothing around that would justify the crowdedness, of course.
  • Tilemolester says the graphics for Bowser In-Game (the monster that is destroying Tokyo) are at $20000, so I guess the program means $04/8000. The graphics fill the whole bank. Man, this game is small!
  • The last bank ($0F/8000 ingame, this game is small!) consists of the messages for Dr. Wright for all the ingame announcements. In plain ASCII code. The missions descriptions are not there, they seem to compressed in one way or another.
  • At $2A000 (so... $05/A000?) are the UFO graphics, followed by the roads and stuff.
  • $7E0CA5 contains the city level. This ZSNES Cheat Search function is great.
  • The 15th Bit in the tiles has nothing to do with electricity supply. If it is set, a 3x3 square gets generated. This is useful for positioning 3x3-buildings. It doesn't work for bigger buildings, like power plants or ports.
  • The subroutine at $03/CE8B loads the start values for the scenarios into the RAM registers. There are tables at $03/CEC9 onwards for this, each with eight doublebyte entries. The value in $CEE9+Y is the city level, $CEF9+Y is the population's lower double byte, $CF09+Y is the population's higher double byte.
  • $40 contains the scenario number, if I hadn't mentioned that before.
  • The city's name is stored at $7E0B5C onwards. This ZSNES Cheat Search function is really great.
  • City name is coded in #$00 - #$09 numbers, from #$0A on alphabet, signs should be after the alphabet.
  • $7E0B5B contains the length of the name (max. 8, the zero doesn't count, so #$04 means: four letters). If you diminish it through RAM editing/ARP code, the name of the city on the small radar when you scroll the map is cut off (the next time that graphics have to load, i. e. when you leave the screen for a menu and return)
  • For the scenarios, you find a 16-bit address table at $03/CF32 (=$01CF32 in ROM). The addresses are bound to that bank and point to the scenario cities' names. These addresses are in a list themselves that you can find at $CF44 onwards. The first byte is the number of letters, the rest is the name. The first byte gets transfered in $7E0B5B (see above). If you ever want to change the name, luckily you have some #$10s of byte free space at the end of the bank. The subroutine that does the ROM read-out and name setup is $03/CF32.
  • $7E00B5 contains the HDMA flags.
  • $7E00B7 contains the DMA flags (maybe someone should write a proper RAM map?).
  • The code at $00/81BF shows that registers $7E0016-21 are buffers for $210D-12.
  • The subroutine at $00/833A shows that registers $7E005F-71 are buffers for registers around $2100/30.
  • OAM-Buffer is at $7E2000 (see $00/8D65).
  • If I see correctly, the whole tileset for the scenario screen is compressed as the scenario city map data (LDA #$0008, COP #$00), and fairly unorganized. So editing the city name and image will be a mess, unless someone writes a nice de-/recompressor tool with Editing GUI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment