Animal Crossing Nes Games Codes

  1. Animal Crossing Nes Games Codes List
  2. Animal Crossing Nes Games Codes New
  3. Animal Crossing Gamecube Fruit Codes
GC

Unlock More NES Games in Animal Crossing

by Jonathan Metts - December 10, 2002, 5:56 pm EST
Source: Datel

Codes

...as long as you don't mind cheating. Also: Freeloader almost done, to be sold in North America as well as Europe.

Today Datel, makers of InterAct's popular GameShark devices and the upcoming Action Replay cheating devices for GameCube and Game Boy Advance, confirmed to PGC that they are in the final stages of production for both the GameCube Action Replay and the long-awaited Freeloader import disc.

Never Get Resetti 6V2F-BURM-6RGKP 27X9-2EX8-WMDU0 Due to the way Animal Crossing works this code is essential to avoid having Resetti popping up and reaming your ears out.

The Freeloader is a GameCube boot disc that allows you to play games from any region on any GameCube. (For NTSC-to-PAL conversions, you may need a special TV or converter.) Announced months ago, the Freeloader has been delayed time and time again, and many thought it would never see the light of day. Now Datel says not only should the Freeloader be in stores by the end of the year, but it will now be released in North America as well as Europe.

As for the new NES games in Animal Crossing, as you may have guessed by now, unlocking them early requires the GameCube Action Replay. This information could be considered a SPOILER, so scroll down if you really want to know which games are left on the disc.























It's been known that both Super Mario Bros. and The Legend of Zelda are both hidden on the Japanese version of Animal Crossing. We can now confirm that both are included in the North American version as well. There's no telling when Nintendo will announce the in-game codes to unlock these treasured classics, but you can get them much earlier with the Action Replay. Datel has already discovered an Action Replay code to unlock Zelda, and they are currently working on one to unlock Mario as well. Remember that once these games are unlocked, you can also download them to your GBA for portable play.

Datel Splits with InterAct

The maker of the GameShark will now market the device as Action Replay in the US and finally release a version for GameCube.

DATEL ELECTRONICS ENDS DISTRIBUTION AGREEMENT WITH INTERACT ACCESSORIES

Clearwater, FL - December 5, 2002 - Datel Electronics, the world’s leading developer and manufacturer of videogame enhancement products has terminated its distribution agreement with InterAct Accessories and will no longer supply game enhancers or hardware accessories sold under the GameShark™ brand.

Over the past 6 years, the Datel developed, and GameShark™ branded, game enhancers have become the most popular cheat device in North America selling in excess of 4 million units.

In response to the overwhelming demand, Datel will begin distributing its line of game enhancers and leading edge accessories direct to retailers under the Action Replay brand through its US based corporation, Datel Design & Development, Inc., located in Clearwater, Florida.

“Although our relationship with InterAct has ended, we continue on with the technology, creative talent and manufacturing expertise to expand on what we started a number of years ago”, says Mike Connors, Managing Director of Datel Electronics, LTD. “We look to the future with great excitement and a commitment to continue building next generation products that will further enhance the gaming experience.”

Datel will officially kick off its US launch with the much anticipated release of the first and only game enhancement solution for the GameCube platform. Created by the same team that developed software for the GameShark™, Action Replay for GameCube will come loaded with codes for every GameCube title released at the time of manufacture. As expected by millions of fans, free code updates will be available at the company’s official Action Replay website, www.codejunkies.com. Action Replay for GameCube is set to provide gamers with the extra lives, ammo, level selects, and other cheats they’ve come to expect from Datel’s seasoned team of hackers. Expect the Action Replay for GameCube to hit stores in late December at a retail price of $39.99.

For the PlayStation 2 platform, Datel continues its domination with a full line of game enhancement products. To ensure gamers experience a seamless transition from the GameShark™2, the Action Replay for PS2 employs the same user interface and code type format. All Action Replay codes will be 100% compatible with their GameShark™2 counterparts, ensuring no gamer using Datel designed technology will be left in the cold. Action Replay is also 100% backward compatible with InterAct’s previously sold SharkPort and SharkBoard branded hardware accessories.

Action Replay for PS2 comes complete with an unprecedented 17,000 pre-loaded game codes for hundreds of the hottest PS2 games including GTA Vice City and Tony Hawk 4, as well as an 8 megabyte memory card to store tons of new codes or game saves for only $39.99. Datel is also releasing a limited edition version of Action Replay with a 16 megabyte memory card for only $49.99. Both products launch in December. As always, free code updates will be posted daily at the company’s official Action Replay website, www.codejunkies.com.

For the budget conscious gamers, Datel has introduced a new line of inexpensive game enhancing alternatives under the Ultimate Codes brand. Each title provides a broad library of hot cheat codes expertly hacked by our in-house staff, for a single, hot-selling game. The Ultimate Codes product line will be available for both the PlayStation 2 and GameCube consoles and retail for $9.99.

To compliment its Action Replay branded software, Datel will continue to provide two of their highly successful hardware accessories for the PS2 platform as well as a third accessory that is sure to become a hit.

The X-Port, previously named SharkPort, allows gamers to connect their PS2 with a PC, providing game save storage capabilities limited only be the size of their PC’s hard drive. Additionally, game saves can be emailed to friends, or downloaded from online save sites. Action Replay code saves found at www.codejunkies.com can be downloaded and used immediately, eliminating the need to enter codes by hand. X-Port retails for $29.99 and is available now.

The PowerBoard, is a full function USB keyboard designed to work with the new Action Replay, and original GameShark™2, making new code entry faster and easier. The PowerBoard also acts as a controller for keyboard compatible PS2 First Person Shooters and many of the exciting new on-line enabled games. The PowerBoard retails for $19.99 and is available now.

To support the burgeoning growth of on-line gaming for PlayStation2, Datel is releasing a network/broadband adapter called Go-Net. Go-Net comes complete with the hardware and setup software necessary to allow gamers to immediately enjoy some of the hottest on-line enabled games to hit the market this Holiday season. Go-Net will be available in December and retail for $29.99.

Last but not least, Datel has not abandoned its Game Boy Advanced fans. Action Replay for GBA will release in January loaded with codes for the hottest game releases of the year. What’s even more exciting is that Datel will be releasing its Action Replay for GBA with a retail price of just $19.99!

Visit www.codejunkies.com to learn more about Datel’s exciting lineup of products.

Related Content

Most Popular News Stories

Other News Stories

While looking for ways to activate the developer menus left over in Animal Crossing,including the NES emulator game selection menu, I found an interesting feature that existsin the original game that was always active, but never used by Nintendo.In addition to the NES/Famicom games that can be obtained in-game, it was possible toload new NES games from the memory card.I was also able to find a way to exploit this ROM loader to patch custom code and data intothe game, allowing for code execution via the memory card.

Introduction - The NES console items

The normal NES games that you could obtain in Animal Crossing each came as an individualfurniture piece that appeared as an NES console with a single game box on top of it.When you placed the item in your house and interacted with it, it would only play that one game.Pictured below are the Excitebike and Golf items.

There was also a generic “NES Console” item that did not feature any of the built-in games.You could buy this item from Redd, or sometimes obtain it through random events such astown bulletin-board message stating that one has been buried in a random location in town.

This item appeared as the NES console with no game boxes on top of it.

The problem with this item is that it was thought to be unplayable. Every time youinteracted with it, you would just see a message indicating that you didn’t have anysoftware to play.

It turns out that this generic console item actually attempts to scan the memory card forspecially constructed files that contain NES ROM images! The NES emulator used to playthe built-in games is apparently a complete, generic NES emulator for the GameCube, andit’s capable of playing most games thrown at it.

Before demonstrating these features, I’ll explain the process of reverse engineering them.

Finding the memory card ROM loader

Looking for dev menus

My original intention was to find code that activates the various developer menus, suchas the map select menu or NES emulator game select menu. The“Forest Map Select” menu,which makes it easy to instantly load directly into different locations in the game,was easy enough to locate just by searching for the “FOREST MAP SELECT” string thatappears at the top of the screen (as seen in various videos and screenshots online).

The “FOREST MAP SELECT” had a data cross-reference to a function called select_print_wait,which lead to a bunch of other functions that also had the select_* prefix,including one called select_init. These happen to be the functions that handlethe map select menu.

The select_init function lead to another interesting function calledgame_get_next_game_dlftbl. This one ties together all the other menus and “scenes”that can run: the Nintendo logo screen, the title screen, the map select menu,the NES (Famicom) emulator menu, and so on. It runs early in the main procedureof the game, looks up which scene initialization function it should run, and finds itsentry in a table data structure called game_dlftbls. This table holds references tothe different scene handling functions, as well as some other data.

A close up of the first block of the function shows that it loads the “next game init”function, and then starts comparing it to a series of known init functions:

  • first_game_init
  • select_init
  • play_init
  • second_game_init
  • trademark_init
  • player_select_init
  • save_menu_init
  • famicom_emu_init
  • prenmi_init

One of the function pointers it checks for is famicom_emu_init, which is responsible forstarting up the NES/Famicom emulator. By forcing the result of game_get_next_game_initto be famicom_emu_init or select_init in the Dolphin debugger, I can get the specialmenus to display. The next step is to figure out how these pointers would normally beset during runtime. All the game_get_next_game_init function does is load a valueat offset 0xC of the first argument to game_get_next_game_dlftbl.

Tracking how these values got set across various data structures was a bit tedious,so I’ll just cut to the chase. The main things I found were:

  • When the game starts up normally, it goes through this sequence:
    • first_game_init
    • second_game_init
    • trademark_init
    • play_init
  • player_select_init will set the next init to select_init. This screen is supposed toallow for player selection just before map selection, but didn’t seem to be working correctly.

There was also one unnamed function that would set the emulator init function, but nothingappeared to set the init function to the player or map select inits.

At this point I realized I had another silly issue with how I loaded function namesinto IDA, where I was missing any function names that began with a capital letterdue to the regular expression I used to cut out lines in the debug symbol file.The function that would set up famicom_emu_init looked related to scene transitions,and indeed its name turned out to be Game_play_fbdemo_wipe_proc.

Game_play_fbdemo_wipe_proc handles scene transitions such as screen wipes and fades.Under certain conditions, the screen transition leads from normal gameplay into theemulator display. That’s what will set the emulator init function.

Console furniture handling

What causes the screen transition handler to switch over to the emulator isactually the furniture item handler functions for the NES consoles.aMR_FamicomEmuCommonMove is called when a player interacts withone of the consoles.

When this function is called, r6 holds an index value corresponding to the numbers seenin the filenames of the NES games in famicom.arc:

  • 01_nes_cluclu3.bin.szs
  • 02_usa_balloon.nes.szs
  • 03_nes_donkey1_3.bin.szs
  • 04_usa_jr_math.nes.szs
  • 05_pinball_1.nes.szs
  • 06_nes_tennis3.bin.szs
  • 07_usa_golf.nes.szs
  • 08_punch_wh.nes.szs
  • 09_usa_baseball_1.nes.szs
  • 10_cluclu_1.qd.szs
  • 11_usa_donkey3.nes.szs
  • 12_donkeyjr_1.nes.szs
  • 13_soccer.nes.szs
  • 14_exbike.nes.szs
  • 15_usa_wario.nes.szs
  • 16_usa_icecl.nes.szs
  • 17_nes_mario1_2.bin.szs
  • 18_smario_0.nes.szs
  • 19_usa_zelda1_1.nes.szs

(.arc is a proprietary file archive format.)

When r6 is non-zero, it’s passed along in a call to aMR_RequestStartEmu.This eventually triggers the emulator transition.

However, if r6 is zero, a function named aMR_RequestStartEmu_MemoryC is called instead.Setting the value to zero in the debugger, I got the “I don’t have any software” message.I didn’t recall the generic “NES Console” item right away to see if that’s what wouldcause r6 to be zero, but it is - index zero is used for the generic console item.

While aMR_RequestStartEmu just stores the index value to some data structure,aMR_RequestStartEmu_MemoryC does something much more complex…

That third code block calls aMR_GetCardFamicomCount and checks for a non-zero result,or else it will short-circuit past most of the interesting stuff on the left side ofthe function graph.

aMR_GetCardFamicomCount calls into famicom_get_disksystem_titles, which then callsinto memcard_game_list, which is where things start to get really interesting.

memcard_game_list will mount the memory card and start looping through its file entries,checking some values on each one. By tracing through it in the debugger, I could see whatit was comparing the values to on each of my memory card files.

Whether or not the function decides to load in a file depends on a few string comparison checks.First, it checks for the presence of the strings “GAFE” and “01”, which are the game IDand company ID, respectively. The 01 refers to Nintendo, “GAFE” refers to Animal Crossing.My guess is that it’s short for “GameCube Animal Forest English”.

Then it checks for the strings “DobutsunomoriP_F_” and “SAVE”. In this case,the first string should match, but not the second. “DobutsunomoriP_F_SAVE” happens to bethe name of the file that stores save data for the built-in NES games.So, any file besides that with the “DobutsunomoriP_F_” prefix will be loaded.

By using the Dolphin debugger to skip over the “SAVE” string comparison and trickthe game into thinking my “SAVE” file was OK to load, I got this menu to show up whenI used the NES console:

I answered yes and attempted to load the save file up as a game, and got the built-incrash screen for the first time:

Cool! Now that I know it is in fact trying to load games from the memory card,I can start figuring out the format for the save files to see how to load up a realROM.

One of the first things I tried to do was find out where the game name was beingread from in the memory card file. By searching for the string “FEFSC” that appears inthe “Would you like to play <name>?” message, I found the offset where it was being readfrom in the file: 0x642. By copying the save file, changing the filename to“DobutsunomoriP_F_TEST”, setting the bytes at offset 0x642 to “TESTING”, and re-importingthe edited save, I could get the desired title name to display in the menu.

Adding multiple files in this format resulted in more options being added to the menu,as seen here:

Booting a ROM file

If aMR_GetCardFamicomCount returned non-zero, some memory is allocated on the heap,famicom_get_disksystem_titles is called again directly, and then a bunch of randomoffsets in a data structure get set. Instead of deciphering where all these valueswere going to be read, I started looking at the list of famicom functions.

famicom_rom_load turned out to be the right place to look. It handles ROM loading,whether from a memory card or the internal game resources.

The most significant thing in the “memory card load” block is that it callsmemcard_game_load. This mounts the file on the memory card once again, reads it in,and parses it. The most important features of the file format become apparent here.

Checksum value

The first thing that happens after the file is loaded is a checksum calculation.The calcSum function is called, which is a very simple algorithm that sums upthe values of all the bytes in the memory card data. The low eight bits of theresult must be zero. So, to pass this check, you have to sum up the values of allthe bytes in your original file, figure out what value to add to that sum tocause the low eight bits to be zero, and then set a checksum byte in your fileto that value.

If the check fails, you get a message stating that the memory card couldn’tbe read correctly, and nothing happens.During the debugging process, all I have to do is skip over this check.

Copying the ROM

Down near the end of memcard_game_load, another interesting thing happens.There are some more interesting code blocks between this and the checksum, but none ofthem will result in a branch that skips over this behavior.

If a certain 16-bit integer read from the card is non-zero, a function will be called to check fora compression header on a buffer. It checks for some proprietary Nintendo compression formats bylooking for “Yay0” or “Yaz0” at the beginning of the buffer. If one of these is found,a decompression function is called. Otherwise, a simple memory copy function is performed.Either way, a variable called nesinfo_data_size is updated afterwards.

Another context clue here is that the ROM files for the built-in NES games use “Yaz0” compression,and have that string in their file header.

By observing the value that’s checked for zero and the buffer that’s passed to the compressioncheck functions, I can quickly identify where in the memory card file the game is reading from.The zero-check is performed against part of a 32 byte buffer that’s copied from offset 0x640in the file, which is likely a header for the ROM. Other parts of it are also checked throughoutthis function, and it’s where the game title is located (starting from the third byte of the header).

With the specific code path I hit, the ROM buffer is located immediately after this 32 byteheader buffer.

This is enough information to attempt to construct a valid ROM file. I simply took one of the otherAnimal Crossing save files and edited it with a hex editor to change the name of the file toDobutsunomoriP_F_TEST and clear out the areas where I needed to insert data.

I used the Pinball ROM that’s already present in the game for this test run, and copied its contentin after the 32 byte header for a test. Instead of calculating the checksum value, I also set somebreakpoints so that I could just skip over calcSum, as well as observe the results of other checksthat might cause a branch that skips past loading the ROM.

Finally, I imported the new file through the Dolphin memory card manager, restarted the game,and went to try it out on the console.

It worked! There were some graphical quirks caused by Dolphin settings that affect thegraphics mode used by the NES emulator, but the game played just fine.(In newer Dolphin builds it should work by default.)

To be sure that other games would work, I tried out some more ROMs that weren’t already presentin the game. Battletoads would start up, but not continue past the intro text (with some moretweaking later on, it did become playable).Mega Man, on the other hand, worked perfectly:

To be able to generate more ROM files that could load without any debugger interventionI’d have to start writing code and dig into the file format parsing some more.

The external ROM file format

Most of the critical file parsing happens in memcard_game_load. There are six main sectionsto the parsing code blocks in this function:

  • Checksum
  • Save file name
  • ROM file header
  • Unknown buffer that’s copied without any processing
  • Text comment, icon, and banner loader (for new save file creation)
  • ROM loader

Checksum

The low eight bits of the sum of all the byte values in the save file must be zero.Here’s some simple Python code that generates a checksum byte that can achieve that:

There’s probably a designated location to store the checksum byte, but justplacing it in empty padding space at the very end of the save file works fine.

File name

Just to reiterate, the save file name must begin with “DobutsunomoriP_F_” and endwith something other than “SAVE”. This filename is copied a couple of times,and in one case the letter “F” is replaced with “S”. This will be the name ofsave files for the given NES game (“DobutsunomoriP_S_NAME”).

ROM header

A direct copy of the 32 byte header is loaded into memory. A few of the valuesin this header are used to determine how to handle the upcoming sections.It mainly includes some 16-bit size values and packed setting bits.

If you trace the pointer that the header is copied toall the way to the beginning of the function and figure out its argument position,the function signature below reveals that its type is in fact MemcardGameHeader_t*.

Unknown buffer

A 16-bit size value from the header is checked. If it’s non-zero, that numberof bytes will be directly copied from the file buffer into a new block of allocatedmemory. This advances a datapointer in the file buffer so that copying can resume from the next sectionlater on.

Banner, icon, and comment

Another size value is checked in the header, and if it’s non-zero the compression checkfunction is called. If necessary the decompression algorithm will run, and then SetupExternCommentImageis called.

This function handles three things: a “comment”, a banner image, and an icon. For each one there’s a codein the ROM header that indicates how it should be handled. The options are:

  1. Use a default value
  2. Copy from the ROM file banner/icon/comment section
  3. Copy from an alternate buffer

The default value code will cause the icon or banner to be loaded from an on-disk resource,and the save file name and comment (a text description of the file) to be set to“Animal Crossing” and “NES Cassette Save Data” respectively. This is how it would look:

The second code value will just copy the game name from the ROM file (some alternative to“Animal Crossing”), and then attempt to find the string “] ROM” in the file comment and replace itwith “] SAVE”. Presumably, the files Nintendo intended to release would have a name format like“Game Name [NES] ROM”, or something similar.

For the icon and banner it would attempt to figure out the format of the image, get a fixed size valueaccording to that format, and then copy the image over.

For the last code value, the file name and description would be copied from another buffer withoutany changes, and the icon and banner would be loaded from the alternate buffer as well.

ROM

If you look carefully at the memcard_game_load screenshot of the ROM copying,the 16-bit value that’s checked for zero is left shifted by 4 bits (multiplied by 16)and then used as the size for the memcpy function when no compression is detected. This isanother size value present in the header.

If the size is non-zero, the ROM data is checked for compression and then copied over.

The unknown buffer and the search for bugs

While getting new ROMs to load up was pretty cool, one of the most interesting things about this ROM loader to mewas that it’s virtually the only thing in the game that accepts variable-size user input and copies it to differentplaces in memory. Almost everything else uses fix-sized buffers. Things like names and letter text might seem likethey’re variable in size, but the empty space is basically filled with space characters. Null-terminated strings arenot used often, preventing some common memory corruption bugs such as using strcpy on a buffer that’s too smallfor the string being copied over to it.

I was really interested in finding a save file based exploit in the game, and this seemed like the best bet.

Most of the ROM file handling described above also used fixed-size copies, except for the unknown buffer and ROM data.Unfortunately, the code that handles this buffer allocates just as much space as is needed to copy it, so there’s no overflow,and setting really large ROM file sizes wasn’t very useful.

Still, I wanted to know what was going on with that buffer that would be directly copied without any handling.

The NES Info Tag processors

Revisiting famicom_rom_load, a few functions are called after a ROM gets loaded from the memory card or disk:

  • nesinfo_tag_process1
  • nesinfo_tag_process2
  • nesinfo_tag_process3

By tracing where the unknown buffer was copied to, I verified that it was being operated on by these functions.These start by calling nesinfo_next_tag, which goes through a simple algorithm:

  • Check if the given pointer matches the pointer in nesinfo_tags_end. If it’s less than nesinfo_tags_end, or nesinfo_tags_endis zero, it checks if the string “END” is present at the head of the pointer.
    • If “END” has been reached, or the pointer has advanced up to or past nesinfo_tags_end, the function returns zero (null).
    • Otherwise, the byte at offset 0x3 of the pointer is added to 4 and the current pointer, and that value is returned.

This suggests a tag format of some three letter name, a data size value, and data. The result is a pointer to the next tag,as the current tag will be skipped over (cur_ptr + 4 skips the three byte name and one byte size, and size_byte skips over the data).

If the result is non-zero, the tag processing function then goes through a series of string comparisons to figure outwhat tag to handle. Some of the tag names checked for in nesinfo_tag_process1 are VEQ, VNE, GID, GNO, BBR, and QDS.

If a tag is matched, some handler code is executed. Some of the handlers do nothing but print the tag to a debug message.Others have more complex handlers. After a tag is processed, the function attempts to get the next tag and continueprocessing.

Luckily, there are a bunch of descriptive debug messages that get printed outwhen these tags are found. They’re all in Japanese, so they have to be Shift-JIS decoded and translated first.The messages for QDS, for example, can say “Load Disk Save Area” or “Since it is the first play, keep the disk save area”.The messages for BBR say “battery backup load” or “because it is the first play, clear”.

Both of these codes also load some values from their tag data section and use them to calculate an offset into the ROM dataand then perform copy operations.It’s apparent that they’re responsible for designating parts of the ROM memory that are related to saving state.

There’s also an “HSC” tag that has a debug message indicating that this handles high scores. It takes an offsetinto the ROM from its tag data, as well as an initial high score value. These tags can be used to mark where high scorevalues are kept in the NES game’s memory, probably so that it can be saved and restored later.

These tags provide a fairly complex system for loading metadata about the ROMs. Even better, many of them resultin memcpy calls based on values provided in the tag data.

Bug hunting

Most of the tags that caused memory manipulation weren’t going to be very useful for exploits, because they allhad maximum offset and size values represented by 16-bit integers. This is all that would be needed to handlethe 16-bit address space of the NES, but doesn’t provide much range for writing over useful targets suchas function pointers or return addresses on the stack in the 32-bit address space of the GameCube.

However, there were a few cases where offsets or size values passed to memcpy could exceed 0xFFFF.

QDS

QDS actually loads a 24-bit offset from its tag data, as well as a 16-bit size value.

The good thing is that the offset is used to calculate the destination of a copy operation.The base address for the offset is the beginning of the loaded ROM data, the source of the copyis in the memory card ROM file, and the size is the given 16-bit size value from the tag.

A 24-bit offset has a maximum value of 0xFFFFFF, which is well above what’s needed to writeoutside the boundary of the loaded ROM data. There are some problems, though…

The first is that even though the maximum size value is 0xFFFF, it’s initially used to zeroout a section of memory. If the size value is too high (not much more than 0x1000), this willactually zero out the “QDS” tag in the game’s code.

This is a problem because nesinfo_tag_process1 actually gets called twice. The first time, it willcollect some information about space it needs to set up for save data. The QDS and BBR tags are notfully processed on the first run. After the first run, some space is set up for save data, andthe function is called again. This time the QDS and BBR tags would be fully processed,but it’s impossible to match the tags again if the tag name strings have all been cleared out ofmemory!

So, setting a smaller size value can avoid that. The other problem is that the offset valuecan only go forwards in memory, and the NES rom data is located on the heap fairly closeto the end of usable memory.

There are only a few heap entries that come after it, none of which had anything super usefullike obvious function pointers.

Normally it might be possible to use this for a heap overflow exploit, but the malloc implemenationused for this heap actually adds a load of sanity check bytes into the malloc blocks. It’s possibleto write over pointer values in the subsequent heap blocks. Without the sanity checking, this could beused to write an arbitrary value to an arbitrary location in memory when free is called on theaffected heap block.

However, the malloc implementation used here will check for a specific byte pattern (0x7373) at the beginning of thenext and previous blocks it’s going to manipulate upon the call to free. If it doesn’t find those bytes,it calls OSPanic and the game stops.

Without being able to influence those bytes to be present atsome target location, it’s not possible to write there. In other words, you can’t write something toan arbitrary location without already being able to write something right next to that location.There could be some way to get the value 0x73730000 to be stored on the stack right before a return address,and the location referenced by the value you want to write to the destination address (it will also be checkedas if it’s a pointer to a heap block), but it’d be difficult to find and exploit.

nesinfo_update_highscore

Another function involving the QDS, BBR, and HSC tags is nesinfo_update_highscore.The QDS, BBR, and OFS (offset) tag size values are used to calculate an offset to write to, and anHSC tag triggers a write to that location. This function runs for every frame processedby the NES emulator.

The maximum offset value per tag in this case, even for QDS, is 0xFFFF.However, during the tag processing loop, sizevalues from BBR and QDS tags actually get accumulated. This means that multiple tagscan be used to calculate just about any offset value. The limit is the number of tagsthat can be fit in the ROM tag data section of the memory card file,which has a maximum size of 0xFFFF as well.

The base address that the offset gets added to is 0x800C3180, the save data buffer.This is at a much lower address than the ROM data, providing more freedom in choosingwhere to write to. Writing over the function’s return address on the stack at 0x812F95DC,for example, would be fairly easy.

Unfortunately, this doesn’t work either. nesinfo_tag_process1 happens to also figure outthe accumulated size of the offsets from these tags, and uses that size to initializesome space like this:

With the offset value I tried to calculate, this resulted in 0x48D91EC (76,386,796)bytes of memory getting wiped out, causing the game to crash spectacularly.

Animal Crossing Nes Games Codes

The PAT tag

Animal Crossing Nes Games Codes List

It was starting to look hopeless, as all of the tags that made unsafe calls to memcpy wouldend up causing a crash before they could be useful.I decided to switch over to just documenting the purpose of each tag, and eventually reached thetags in nesinfo_tag_process2.

Most of the tag handlers in nesinfo_tag_process2 will never run because they only workwhen the pointer nesinfo_rom_start is not null. Nothing in the code ever sets that pointerto be non-null. It gets initialized to zero, and never gets used again.Only nesinfo_data_start is set when a ROM gets loaded, so this looks like a piece of dead code.

There is one tag that can still operate when nesinfo_rom_start is null, though: PAT.This is the most complex tag in the nesinfo_tag_process2 function.

It still uses nesinfo_rom_start as a pointer, but never performs a null check on it.The PAT tag will read through its own tag data buffer, processing codes that calculate offsets.Those offsets are added to the nesinfo_rom_start pointer to calculate a destination address,and then bytes are copied from the patch buffer into that location. This copy is performed withload and store byte instructions, rather than memcpy, which is why I hadn’t noticed itsooner.

Each PAT tag data buffer has an 8-bit type code, 8-bit patch size, and 16-bit offset value,followed by the patch data.

Animal Crossing Nes Games Codes
  • If the code is 2, the offset value is added to the current offset sum.
  • If the code is 9, the offset is shifted up 4 bits and added to the current offset sum.
  • If the code is 3, the offset sum is reset to 0.

The largest size an NES info tag can have is 255, so the largest possible PAT entry patchsize is 251 bytes. Multiple PAT tags are allowed, though, so it’s possible to patch morethan 251 bytes, as well as patch non-contiguous locations.

So long as there’s a series of code 2 or code 9 PAT sub-tags, the destination pointer offset continues to accumulate.It will be reset to zero when patch data gets copied, but using a patch size of zero avoids this.Writing this now, it’s clear that this could be used to calculate some arbitrary offsetagainst the null pointer in nesinfo_rom_start by using lots of PAT tags.

However, there are two more code value checks…

  • If the code is between 0x80 and 0xFF, it gets added to 0x7F80 and then shiftedup 16 bits. Finally, this is added to the 16-bit offset value and used as the destinationaddress to patch.

This allows setting any address in the range 0x80000000 to 0x807FFFFF as the destinationfor the patch! That’s where a bunch of the code for Animal Crossing lives in memory.This means its possible to patch Animal Crossing’s code itself using the ROM metadatatags from a file on the memory card.

With a small loader patch, it’d be possible to easily load even larger patches to any addressfrom the memory card.

For a quick test, I set up a patch that would turn on “zuru mode 2” (the game’s developer mode, describedin my last blog post) when the user loads a ROM from the game card. It turns out thatthe button cheat combo only activates “zuru mode 1”, which doesn’t have access to all thesame features that mode 2 has. With this patcher, it’s now possible to get full accessto developer mode on real hardware using a memory card.

The patch tags will be processed as the ROM is loaded up.

After the ROM loads, exit the NES emulator to see the result.

It works!

Patcher info tag format

The info tags in the save file that performs this patch look like this:

  • ZZZ x00: An ignored beginning tag. 0x00 is the size of its data buffer: zero.
  • PAT x08 xA0 x04 x6Fx9C x00x00x00x7D: Patches 0x80206F9C to 0x0000007D.
    • 0x08 is the size of the tag buffer.
    • 0xA0, when added to 0x7F80, is 0x8020, the upper 16 bits of the destination address.
    • 0x04 is the size of the patch data (0x0000007D).
    • 0x6F9C is the lower 16-bits of the destination address.
    • 0x0000007D is the patch data.
  • END x00: The end marker tag.

If you want to experiment with creating patcher or ROM save files yourself, I have some simplecode at https://github.com/jamchamb/ac-nesrom-save-generator for generating the files.A patch like the one above can be generated with the following command:

Animal Crossing Nes Games Codes New

Arbitrary code execution

With this tag it’s possible to gain arbitrary code execution in Animal Crossing.

There’s one last hurdle: using patches against data works fine, but something’s wrongwith patching code instructions.

While the patches do get written, the game continues to execute the old instructions thatwere there before. It seems like a caching issue, and in fact it is.The GameCube CPU had instruction caches, as seen in https://en.wikipedia.org/wiki/Nintendo_GameCube_technical_specifications.

To figure out how the cache could be cleared, I started looking up cache related functionsin the GameCube SDK documentation, and found ICInvalidateRange. This functionwill invalidate cached blocks of instructions at a given memory address, allowing modified instructionmemory to execute with the updated code.

Without a way to get initial code to run, it’d still be impossible to call ICInvalidateRange,though. Getting successful code execution will require one more trick.

Animal Crossing Gamecube Fruit Codes

While looking over the malloc implementation to figure out if a heap overflow exploit was possible,I learned that the malloc implementation functions could be switched out dynamically through a data structureand function named my_malloc. my_malloc would load a pointer to the current malloc or free implementationfunction from a static location in memory, and then call that function while passing along whatever arguments weregiven to my_malloc.

The NES emulator used my_malloc heavily to allocate and free memory for NES ROM-related data, so Iknew it would be triggered multiple times around the same time that the PAT tags get processed.

Because my_malloc would load a pointer from memory and then branch to it, I could alter the control flowof the program just by overwriting the pointer for the current malloc or free functions. Instruction cachingwould not prevent this from running, as none of the instructions in my_malloc need to be changed.

Cuyler, the developer of the Dōbutsu no Mori e+ fan translation project, implemented a loader in PowerPC assemblyand demonstrates using it to inject new code in this video: https://www.youtube.com/watch?v=BdxN7gP6WIc.(Dōbutsu no Mori e+ was the last iteration of Animal Crossing on GameCube, which has the most updates and wasonly released in Japan.)After being injected with PAT tags, the loader can read much larger patches from the memory card,bypassing the size restrictions of the tag info section in ROM files.In the demonstration video it loads in some code that allows the player to spawn any object by typing its ID intoa letter and then pressing the Z button.

With that, it will be possible to load mods, cheats, and homebrew using a regular copy of AnimalCrossing on a real GameCube.