Website
Home
Database
News
Submissions queue
Community
Forum
Clubs
Discord
Members
Tools
ROM Patcher
ROM Hasher
Pages
Support us
Learn Romhacking
About
Contact Us
Help & Legal Pages
Guest
Login
Forum
Entries
News
Settings
Community
Tutorials & Guides
Hacking Games In Hex (Sega Genesis Edition)
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="BillyTime Games" data-source="post: 6637" data-attributes="member: 12"><p>Hacking Games in Hex (Sega Genesis Edition)</p><p>Dec. 9th 2024</p><p>BillyTime! Games</p><p>--------------------</p><p></p><h3>(0).Intro</h3><p>Welcome, this tutorial aims to ease newcomers and intermediates into hacking Sega Genesis games via a hex editor.</p><p>You will need a few programs, this tutorial will assume that you are using the following</p><p>*Gens r57 Shell Mod</p><p>*Notepad++</p><p>*HxD</p><p></p><p>I personally would like to thank Jlukas and Tony Hedstrom for giving me the tools and knowledge on how to modify my favorite games.</p><p>My hope is to give back to the community and give you some of my knowledge to make some excellent rom hacks in the future.</p><p></p><h3>(1).Starting Out, RAM Search, Breakpoints and Trace Logs</h3><p>To start off, we will need Gens r57 Shell Mod. This is my preferred emulator of choice when coding.</p><p></p><p>To start, we will be looking at World of Illusion Starring Mickey Mouse and Donald Duck (USA, Korea).</p><p></p><p>The left hand window is our RAM Search, this will help us locate various address stored such as lives and whatnot.</p><p>We are going to look for health to start off. We will search for equal to 1 change and have mickey take damage as seen here.</p><p></p><p>We will repeat this process by taking another hit and searching for equal to 2 number of changes and so on and so forth. (This is the USA rom btw, addresses and locations get changed up slightly across revisions.)</p><p>Eventually we will find that FFA038 is the ram address that stores mickey's health. Real quick, we will press Ctrl+G to open the cheat menu and enter FFA038:0500 as our code.</p><p></p><p>In doing so, Mickey will essentially have Infinite health!</p><p></p><p>The only problem is that this is a ram code and cannot be patched to a rom, for that we will need breakpoints! So first and foremost, we will disable our code.</p><p></p><p>We will open our debugger under tools and click add. We will add FFA038 as our breakpoint and click enable and write.</p><p></p><p>What will happen is that when FFA038 changes value, the game will stop and tell you what code in the game made the write to that ram address. So next step would be to click okay and go and take a hit.</p><p></p><p>So after taking a hit, the game will stop and show you this code highlighted in green. This is the code that causes mickey to lose health when hit.</p><p></p><p>00:F098 9F 28 SUB.B D7,$0038(A0)</p><p></p><p>So the best approach for this would be to use a branch. By using 00F098:6002 in you game genie menu, you can essentially give mickey infinite health!</p><p></p><p>But real quick lets break down the branch routine.</p><p>------------------------------------------------</p><p>60 is to tell the computer to branch regardless with no condition, useful for skipping over things and helps when designing master codes. 02 tells us to skip over two bytes which would mean skipping 00F098 and 00F09A. 6004 would cause a skip over F09C as well and probably isn't ideal.</p><p>There are multiple branch conditions too, for example.</p><p>6702 - Branch if Equal</p><p>6602 - Branch if not equal</p><p>6C02 - Branch if Greater or Equal</p><p>6302 - Branch if Less than</p><p>F08A also adds 1 to D7 which is subtracted from your health. You can also reach the same effect by using 00F08A:4E71</p><p></p><p>4E71 stands for NOP or No Operation. It skips over one byte. Using multiple of these could work when dealing with multiple bytes but its simpler to use a branch instead which took me time to grasp.</p><p>------------------------------------------------</p><p></p><p>By opening World of Illusion in a hex editor such as HxD, the results you came up with can be implemented with ease!</p><p>Pressing Crtl+G will open up your offset menu. We are going to type in F08A and hit enter.</p><p></p><p>When we enter our code, the text will be red to sigfnify that we made changes and have yet to save them.</p><p></p><p>We will save as and create a new file for our new infinite health hack. Note, HxD creates a BAK file which is a back up of the previous revision which is helpful incase something goes incredibly wrong.</p><p>So now our first hurdle....</p><p></p><p>So for this portion, I will introduce you to Trace Logs. By pressing Pause/Break on our keyboard when can halt emulation. It is advised when turning on Trace Logs as it records all machine code to TXT while active.</p><p>I use Notepad++ when reading Trace Logs, it loads quickly and its easy to search and navigate, especially when we hit a break point and want to investigate the code further.</p><p>We will pause our emulation, Hit Ctrl+Shift and R to reset. You should see a black screen sitting at 0 for your red counter.</p><p>From there, we will go to tools, tracer tools and click trace. The we will unpause the emulation until the red screen appears and then pause again and turn off the trace.</p><p></p><p>The last result is interesting as it branches due to A0 not being equal to D1. Those two numbers aren't quite important for what we are doing right now.</p><p>So lets try 0004FC:4E71!</p><p></p><p>Congrats on your first hack. That's pretty much the basics and how I make hacks.</p><p></p><h3>(2).Addition and Subtraction</h3><p>Next up is addition and subtraction. For this segment we will use Sonic 2 (Rev A) as our base.</p><p></p><p>First we will collect a ring or two and check for greater than previous value in Ram Search.</p><p></p><p>We will find eventually that FFFE21 is the ram address that affects rings. From here we will go to our Debugger and enter FFFE21 as our breakpoint, clicking enable and write.</p><p></p><p>From here, we just simply collect a ring!</p><p></p><p>011FE0 is the code that will come up. 011FEA is also interesting but for different reasons. We will circle back. But lets look deeper into this opcode.</p><p></p><p>Addq.w affects a Word address rather than a Byte address. What this means is that this code affects both FFFE20 and FFFE21 rather than just FFFE21 itself. With that said, word addresses should not be used on odd address numbers as the computer gets confused and locks up. For targeting odd number ram addresses, you will simple use a Byte address.</p><p></p><p>So here is the opcode in Hex</p><p>52 78 - Add 1 (Target Word address)</p><p>FE 20 - Target ram address</p><p></p><p>Absolutely dead simple on how to change this. Change 52 78 to 54 78. Now sonic Collects double rings!</p><p></p><p>To subtract, just as simple! Change 52 78 to 53 78. Even numbers add and odd numbers subtract. This opcode has a limit of 8 or so. However other opcodes exist to allow you to add or subtract more when needed.</p><p></p><p>Moving over to 011FEA or more spefically 011FEC. 0064 is hex for 100, the amount of rings Sonic needs to gain and extra life. By changing this you can raise or lower the required rings needed for Sonic to earn an extra life.</p><p></p><p>As a side note, it is a good idea to keep a record of the opcodes you come across and note its functions. When we get into custom coding, this will be a boon. A basic romhacking tool kit that will help you optimize development on any hacks or help with reference when you get stuck.</p><p></p><h3>(3).JMP Command</h3><p>So now we have JMP Commands or as I call them hijacks. This form of coding is about replacing or adjusting code to some free space in the rom and expanding on what is there. Lets continue with Sonic 2 and ram address FFFE21. Lets collect some rings first, then we shall set our breakpoint in the debugger. Then take a hit. This code should pop up.</p><p></p><p>01:2152 - MOVE.W $0000, ($FE20)</p><p></p><p>The above code is responsible for Sonic losing all his rings when hit without a shield. It is six bytes and is perfect for a JMP hijack.</p><p></p><p>The code will be using is 4EF9 ???? ???? where the ? will be filled in with the offset in hex we plan to jump to. Make some free space at the end of the rom to point our code to offset 00100000.</p><p></p><p>So our hijack will look like this.</p><p></p><p>012152:4EF9</p><p>012154:0010</p><p>012156:0000</p><p>-------------------------------</p><p>I like to bookmark the line above with what the code is supposed to do, it helps with locating code faster in case something goes wrong and needs immediate troubleshooting.</p><p></p><p>Here is the line of code you will use.</p><p>0C 79 00 14 00 FF FE 20 6C 0C 31 FC 00 00 FE 20 4E F9 00 01 21</p><p>58 04 78 00 14 FE 20 4E F9 00 01 21 58</p><p></p><p>Okay, that looks complicated.... Lets break it down and detail what everything does.</p><p></p><p>0C79 - CHECK FOR AT LEAST 20 (Hex) RINGS</p><p>0014</p><p>00FF</p><p>FE20</p><p>6C0C - BRANCH IF GREATER OR EQUAL</p><p>----------------------------> BRANCH JUMPS OVER THIS CODE</p><p>31FC - CLEAR ALL RINGS</p><p>0000</p><p>FE20</p><p>4EF9 - JUMP BACK</p><p>0001</p><p>2158</p><p>-----------------------------</p><p>0478 - SUBTRACT.W 0014 (20) FROM FFFE20</p><p>0014</p><p>FE20</p><p>4EF9 - JUMP BACK to the next opcode</p><p>0001</p><p>2158</p><p></p><p>By using this hijack and the above code, Sonic now only loses 20 rings per hit! As an added check sonic will be set to zero rings if he already has 20 or less rings. That way there aren't any added side effects such as ring overflow.</p><p>-------------------------------</p><p>Don't forget that you will need a master code for this particular game, not all games have master codes.</p><p>00031A:602E</p><p></p><h3>(4).Button Mask and Cheat Codes</h3><p>Continuing with Sonic 2, We are going to locate the Ram Address for Button Inputs and create a JMP hijack to create a simple cheat code.</p><p></p><p>To start In RAM Search without pressing any buttons, we are are going to search for equal to value 0. Press and hold the B button and pause the emulation. Now search Not Equal to value 0.</p><p></p><p>Eventually the top RAM address will be FFF604 which I call a button mask. When controllers are polled, it is sent to a RAM address which can be used for reference by the game later.</p><p></p><p>Just about all polling is the same so here are some handy values to look for when searching for a button mask.</p><p>40 - A Button (No other buttons pressed)</p><p>10 - B Button (No other buttons pressed)</p><p>20 - C Button (No other buttons pressed)</p><p>C0 - A Button + Start</p><p>90 - B Button + Start</p><p>A0 - C Button + Start</p><p></p><p>Next, we are going to lose some lives, searching either less than previous value or by searching for number of changes. Eventually FFFE12 will come up as our RAM address.</p><p></p><p>From here, we will reset and return to the title screen. Set FFFE12 as your breakpoint and start you game. The breakpoint will trigger and this opcode will pop up.</p><p></p><p>003C76 move.b #$03, ($FE12)</p><p></p><p>The code here sets Sonic's Lives to 3. If we want we can always change this number to start Sonic with more lives as an added bonus. But to Stick with our Lesson, we will use a JMP command from before in combination with our new button mask that we found.</p><p></p><p>FFFFB1 is our target RAM address. By setting FFFFB0:0007 in your game genie window, it is possible to give Sonic all Seven Chaos Emeralds! Granted this can be done through a cheat in the game's sound test in the options menu, our method will be a lot quicker.</p><p></p><p>We will do this by checking to see if the B button is being held when pressing start at the title screen. If it is, Sonic will recieve all seven chaos emeralds at once!</p><p></p><p>So if you still have the modded file with our ring subtraction code, we can continue to build upon our previous work.</p><p></p><p>003C76:4EF9</p><p>003C78:0010</p><p>003C7A:00A0</p><p>-------------------------------</p><p>11FC - Set Sonic's Lives to 3</p><p>0003</p><p>FE12</p><p>0C39 - Check if B is being held when starting game</p><p>0090</p><p>00FF</p><p>F604</p><p>6606 - Branch if Not Equal</p><p>11FC - Give Sonic all 7 Chaos Emeralds</p><p>0007</p><p>FFB1</p><p>4EF9 - Jump Back</p><p>0000</p><p>3C7C</p><p>-------------------------------</p><p></p><p>That Seemed a bit too easy. Lets expand up this code and add an extra cheat code!</p><p></p><p>-------------------------------</p><p>11FC - Set Sonic's Lives to 3</p><p>0003</p><p>FE12</p><p>0C39 - Check if A is being held when starting game</p><p>00C0</p><p>00FF</p><p>F604</p><p>660C - Branch if Not Equal</p><p>11FC - Give Sonic 50 lives</p><p>0032</p><p>FE12</p><p>4EF9 - Jump Back</p><p>0000</p><p>3C7C</p><p>0C39 - Check if B is being held when starting game</p><p>0090</p><p>00FF</p><p>F604</p><p>6606 - Branch if Not Equal</p><p>11FC - Give Sonic all 7 Chaos Emeralds</p><p>0007</p><p>FFB1</p><p>4EF9 - Jump Back</p><p>0000</p><p>3C7C</p><p>-------------------------------</p><p></p><p>If you notice, our emerald code isn't working. Turns out the there is a small line of code that is overriding our cheat code. This can be found by setting a breakpoint at FFFFB1 and starting the game.</p><p></p><p>This line should pop up</p><p>003CE8 move.w D0,($FE16)</p><p></p><p>What is happening is that D0 had value Zero and is being placed into various ram addresses, effectively cleaning them out.</p><p></p><p>To keep the game from clearing our stolen emeralds, we will use this code.</p><p>003CE8:6002</p><p></p><p>Everything should work as intended now, you can always check the ram addresses to see if the code immediately worked or play around and find out in game. You could also do both!</p><p></p><p>This type of hacking can be pretty rewarding as you can make new cheat codes to have fun with the game in new ways, add them to games that never had cheats or make a game more accessible to someone who struggled to play it before.</p><p></p><p>Next up is going to be fun and a lot trickier. We will be covering SRAM!</p><p></p><h3>(5).SRAM</h3><p>Here we will cover how to use SRAM to Save and Load values for future use. The possibilities are endless when using SRAM. You can Save progress, High Scores, even unlockable characters if you so wish.</p><p></p><p>For this section, we will be using Shinobi III - Return of the Ninja Master (USA) as our example. To get started go to offset 01B0 in your hex editor and paste this line in HxD with Ctrl+B</p><p></p><p>FF FF 52 41 F8 20 00 20 00 01 00 20 02 00 20 20</p><p></p><p>This line is part of the game's header that will tell the system that SRAM is being utilized.</p><p></p><p>Next up is our game's level modifier. We will be running a write breakpoint in the debugger.</p><p>FF37A6</p><p></p><p>Next some initial setup, we will be using the game's level select code and replacing it in favor of a load menu.</p><p></p><p>Let start by enabling level select.</p><p></p><p>Enable Level Select:</p><p>00B67E:4E71</p><p></p><p>Now lets play with the breakpoint on until we reach stage 2. The game will stop and throw up this code.</p><p></p><p>00B0FA:5239 - Add 1 to 00FF37A6 (Go to next stage.)</p><p></p><p>There is enough room to use a code hijack here. Perfect for what we need. Here is the following code to save your progress, annotated to explain each function.</p><p></p><p>Save Code</p><p>00B0FA:4EF9 - JMP to 000FF2B0</p><p>00B0FC:000F</p><p>00B0FE:F2B0</p><p>0FF2B0:5239 - Go To Next Level</p><p>0FF2B2:00FF</p><p>0FF2B4:37A6</p><p>0FF2B6:41F9 - Move 00FF37A6 to A0 (Level Modifier goes here)</p><p>0FF2B8:00FF</p><p>0FF2BA:37A6</p><p>0FF2BC:13FC - Move.b (Enable SRAM)</p><p>0FF2BE:0001 - 01 (Enable SRAM)</p><p>0FF2C0:00A1 - 00A130F1 (Enable SRAM)</p><p>0FF2C2:30F1 - 00A130F1 (Enable SRAM)</p><p>0FF2C4:43F9 - LEA (start of SRAM)</p><p>0FF2C6:0020 - ($00200001),A1 (start of SRAM)</p><p>0FF2C8:0001 - ($00200001),A1 (start of SRAM)</p><p>0FF2CA:1010 - move A0 to D0 (Move Level Modifier Value to D0)</p><p>0FF2CC:0189 - MOVEP.W D0,#$0000(A1) (Move D0 number into sram)</p><p>0FF2CE:0000 - (move D0 number into sram)</p><p>0FF2D0:13FC - MOVE.B #$00,($00A130F1) (Disable SRAM)</p><p>0FF2D2:0000 - (Disable SRAM)</p><p>0FF2D4:00A1 - (Disable SRAM)</p><p>0FF2D6:30F1 - (Disable SRAM)</p><p>0FF2D8:4EF9 - JMP back to 00B100</p><p>0FF2DA:0000</p><p>0FF2DC:B100</p><p></p><p>SO what happened here is that we set A130F1 to 01. This is how we enable SRAM. When this code is active. SRAM code appears at the 2MB mark so we always need to make sure our code is below offset 1FFFFF in order to work. Otherwise our code will only serve to crash the game. We set it back to 00 afterwards to prevent SRAM from always being active. We only need to it for this purpose anyways.</p><p></p><p>NOTE:</p><p>From plutiedev, it is not really reccomended to use $00200001 in case of a power failure.</p><p>Also, a checksum comes in handy when dealing with something like high scores to prevent a game from crashing or bugging out if the is no or corrupt SRAM.</p><p></p><p>Now with the level select active, keep the write breakpoint active on FF37A6 and press start to pause the game and press C the game will throw up this code.</p><p></p><p>00B6AA:13C0 - Move D0 to 00FF37A6</p><p></p><p>We don't want this code constantly active each frame so we will just NOP it out.</p><p></p><p>Disable Level Selection:</p><p>00B6AA:4E71</p><p>00B6AC:4E71</p><p></p><p>Let scroll up a bit, where did that number in D0 come from. Move up to 00B6A4 and there is our answer!</p><p></p><p>00B6A4:1039 Move 00FF37A6 to D0. This is the perfect spot for our hijack!</p><p></p><p>Here is the following code to Load your progress, annotated to explain each function.</p><p></p><p>Load Code:</p><p>00B6A4:4EF9 - JMP to 000FF300</p><p>00B6A6:000F</p><p>00B6A8:F300</p><p>0FF300:41F9 - Load Level Number to A0 (Level Modifier goes here)</p><p>0FF302:00FF</p><p>0FF304:37A6</p><p>0FF306:13FC - Move.b (Enable SRAM)</p><p>0FF308:0001 - 01 (Enable SRAM)</p><p>0FF30A:00A1 - 00A130F1 (Enable SRAM)</p><p>0FF30C:30F1 - 00A130F1 (Enable SRAM)</p><p>0FF30E:43F9 - LEA (start of SRAM)</p><p>0FF310:0020 - ($00200001),A1 (start of SRAM)</p><p>0FF312:0001 - ($00200001),A1 (start of SRAM)</p><p>0FF314:0109 - MOVEP.W #$0000(A1),D0 (Load SRAM into D0)</p><p>0FF316:0000 - (Load SRAM into D0)</p><p>0FF318:1080 - (Move D0 to A0) (Move D0 to Level Modifier)</p><p>0FF31A:13FC - MOVE.B #$00,($00A130F1) (Disable SRAM)</p><p>0FF31C:0000 - (Disable SRAM)</p><p>0FF31E:00A1 - (Disable SRAM)</p><p>0FF320:30F1 - (Disable SRAM)</p><p>0FF322:4EF9 - JMP to 0000B6AA</p><p>0FF324:0000</p><p>0FF326:B6AA</p><p></p><p>So if you have followed along up until this point, congrats! You just recreated one oif my earliest hacks! Shinobi III SRAM. Here are the instructions on how to use it.</p><p></p><p>Saving:</p><p>Game saves after every level past the first round.</p><p></p><p>Loading:</p><p>On Stage 1, Pause your game and press C, a number will pop up indicating what round you left off at. Unpause to load your game.</p><p></p><p>Be sure to fix your checksum afterwards. You can do so with this tool in the link below. Its an older tool so it detects BIN extentions instead of MD.</p><p>[URL unfurl="true"]https://www.romhacking.net/utilities/342/[/URL]</p><p></p><h3>(6).Palettes</h3><p>Under tools, you can select VDP ram to see when certain GFX are loaded in as well as view the current loaded palettes. There are 4 lines of 16 colors.</p><p>Certain colors can be manipulated at and during run time but what we are going to do is change colors on a more permanent basis. We will Use Ghostbusters (World) (v1.1) as our base.</p><p></p><p>Go into a stage and Select Tools, VDP Ram, from there click Copy Pal and open Notepad. Then hit Ctrl+V and you will be given this bit of code.</p><p></p><p>000 000 EEE 46C 68E 8AE 222 844 C86 ECA 24A 0EE 08E 04E 00A 026</p><p>000 000 EEE E60 EA0 EE4 CAE 86E 22E 44A 4EC 0E0 0A0 060 888 444</p><p>000 000 000 AEE EEE ECC CAA A88 866 644 422 A44 000 000 000 000</p><p>000 888 AAA EEE 022 244 466 688 002 204 422 644 004 026 248 000</p><p></p><p>this here represents the numbers associated with each 16 colors across four lines. 000 is black, EEE is white and so on.</p><p></p><p>The first line is our point of interest as this is the line used for the Ghostbuster's uniforms. Open your Ghostbusters rom in HxD and search for</p><p>000 000 EEE 46C 68E 8AE 222 844 C86 ECA 24A 0EE 08E 04E 00A 026 in hex.</p><p></p><p>Match not found! Wait, what?!</p><p></p><p>Turns out something is missing....</p><p></p><p>so this time add a zero to the begining of each number. Your code will look like this.</p><p>0000 0000 0EEE 046C 068E 08AE 0222 0844 0C86 0ECA 024A 00EE 008E 004E 000A 0026</p><p></p><p>Now we have found our palette at offset 01:BE3E</p><p></p><p>Lets replace this line with the following code by using Copy followed by Ctrl+B in HxD:</p><p>0000 0000 0EEE 046C 068E 08AE 0222 0224 0228 044C 024A 00EE 008E 004E 000A 0026</p><p></p><p>If you boot the game up now, you will see that in Ghostbusters have Red Uniforms in game! This is one of many ways to maniulate palettes to give games a fresh coat of paint.</p><p></p><p>Alternatively you can open offset 01:BE3E in Hivebrain and edit colors without tweaking numbers can get a better visual representation of what your colors will look like.</p><p></p><h3>(7).Address and Data Registers</h3><p>So this next part will be a bit tricky to explain but bear with me. The Genesis has eight address registers and eight data registers, A0 - A7 and D0 - D7.</p><p>A7 is normally used as your stack pointer which normally for me means I don't use it so things don't crash unexpectedly.</p><p></p><p>Everything else is usually fair game. Address registers help with locating damage values (SOR2), art pointers (Ghostbusters), level tables (Earthworm Jim) and whatnot.</p><p></p><p>Data registers usually deal with simple math or moving around time sensitive data.</p><p></p><p>Lets use Streets of Rage 2 as an example of how both address registers and data registers are used in calculating damage done to enemies.</p><p></p><p>Run a trace log at the start of Stage 1 while playing as Axel and drop kick the first enemy you see while the trace log is active.</p><p></p><p>Afterwards in Notepad++ open your trace log and Search (Ctrl+F) for 00:545C.</p><p></p><p>You will find the following snippet of code.</p><p></p><p>00:545C 30 2A MOVE.W $008E(A2),D0 A0=00013DAA A1=00013E70 A2=FFFFF500 A3=FFFFEF00 A4=001F10E6 A5=FFFFEE00 A6=FFFFEC80 A7=FFFFFFEE D0=00C80018 D1=FFFE0000 D2=000100D8 D3=FFFF0000 D4=00000002 D5=405CFF00 D6=00D100C4 D7=00C90000 xnZvc</p><p>00:5460 91 6A SUB.W D0,$0080(A2) A0=00013DAA A1=00013E70 A2=FFFFF500 A3=FFFFEF00 A4=001F10E6 A5=FFFFEE00 A6=FFFFEC80 A7=FFFFFFEE D0=00C80008 D1=FFFE0000 D2=000100D8 D3=FFFF0000 D4=00000002 D5=405CFF00 D6=00D100C4 D7=00C90000 xnzvc</p><p></p><p>Lets break it down.</p><p></p><p>At 00:545C FFF58E is moved in to D0, we get this number by adding 8E to FFFFF500 which is located in A2 (Address Register 2).</p><p></p><p>From there, D0 (D0=00C80008) is Subtracted from FFFFF580 (Galsia's Health), this address is found in the same way.</p><p></p><p>In this instance D0 is only using the last four digits (0008) from there we can conclude that Axel's drop kick does eight points of damage to an enemy.</p><p></p><p>Using the XP System Example Code listed below, damage values can be manipulated to be increased or decreased depending on who is getting hit as well</p><p>adding extra conditionals such as damage values based on player score.</p><p></p><h3>(8).Example Code</h3><p>*XP System - Streets of Rage 2(USA)*</p><p>Hijack</p><p>Target Offset</p><p>00545C</p><p></p><p>Enter this code at offset:</p><p>4EF9001FFD00 (Jump to 1F:FD00)</p><p></p><p>Damage Routine (1F:FD00)</p><p>B5FC - Check if Player 1 has been hurt (Compare A2 for FFFFEF00)</p><p>FFFF</p><p>EF00</p><p>6606 - Branch if not equal</p><p>4EF9 - Jump to Defense code (Jump to 1F:FE00)</p><p>001F</p><p>FE00</p><p>B5FC - Check if Player 2 has been hurt (Compare A2 for FFFFF000)</p><p>FFFF</p><p>F000</p><p>6606 - Branch if not equal</p><p>4EF9 - Jump to Defense code (Jump to 1F:FE00)</p><p>001F</p><p>FE00</p><p>302A - Load Damage (MOVE.W $008E(A2),D0)</p><p>008E</p><p>0C2B - Check score (100,000 Points) *Compare 09 at $0096(A3) (FFEF96 or FFF096)*</p><p>0009</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (200,000 Points) *Compare 19 at $0096(A3) (FFEF96 or FFF096)*</p><p>0019</p><p>0096</p><p>6302</p><p>5240</p><p>0C2B - Check score (300,000 Points) *Compare 29 at $0096(A3) (FFEF96 or FFF096)*</p><p>0029</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (400,000 Points) *Compare 39 at $0096(A3) (FFEF96 or FFF096)*</p><p>0039</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (500,000 Points) *Compare 49 at $0096(A3) (FFEF96 or FFF096)*</p><p>0049</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (600,000 Points) *Compare 59 at $0096(A3) (FFEF96 or FFF096)*</p><p>0059</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (700,000 Points) *Compare 69 at $0096(A3) (FFEF96 or FFF096)*</p><p>0069</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (800,000 Points) *Compare 79 at $0096(A3) (FFEF96 or FFF096)*</p><p>0079</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>0C2B - Check score (900,000 Points) *Compare 89 at $0096(A3) (FFEF96 or FFF096)*</p><p>0089</p><p>0096</p><p>6302 - Branch If less</p><p>5240 - Add 1 to damage (Add 1 to D0)</p><p>916A - Subtract Damage (SUB.W D0,$0080(A2) - Subtract D0 from $0080(A2) or FFF580 as an example which is an address for enemy health.)</p><p>0080</p><p>4EF9 - Jump back (Jump to 00:5464)</p><p>0000</p><p>5464</p><p></p><p>Defense Routine (1F:FE00)</p><p>302A - Load Damage (MOVE.W $008E(A2),D0)</p><p>008E</p><p>0C2B - Check score (100,000 Points) *Compare 09 at $0096(A3) (FFEF96 or FFF096)*</p><p>0009</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 19 at $0096(A3) (FFEF96 or FFF096)*</p><p>0019</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 29 at $0096(A3) (FFEF96 or FFF096)*</p><p>0029</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 39 at $0096(A3) (FFEF96 or FFF096)*</p><p>0039</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 49 at $0096(A3) (FFEF96 or FFF096)*</p><p>0049</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 59 at $0096(A3) (FFEF96 or FFF096)*</p><p>0059</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 69 at $0096(A3) (FFEF96 or FFF096)*</p><p>0069</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (100,000 Points) *Compare 79 at $0096(A3) (FFEF96 or FFF096)*</p><p>0079</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>0C2B - Check score (900,000 Points) *Compare 89 at $0096(A3) (FFEF96 or FFF096)*</p><p>0089</p><p>0096</p><p>6302 - Branch If less</p><p>5340 - Subtract 1 to damage (Sub 1 from D0)</p><p>916A - Subtract Damage (SUB.W D0,$0080(A2) - Subtract D0 from $0080(A2)</p><p>0080</p><p>4EF9 - Jump back (Jump to 00:5464)</p><p>0000</p><p>5464</p><p>----------------------</p><p></p><p>*Faster Acceleration - Sonic The Hedgehog 2 (World) (Rev A)</p><p></p><p>Target Offset</p><p>19FCE</p><p></p><p>Enter this code at offset:</p><p>4EF900100040 - (Jump to 10:0040)</p><p></p><p>Routine:</p><p>31FC - Move 000C to FFF762 (Set Normal Acceleration for Sonic)</p><p>000C</p><p>F762</p><p>0C39 - Compare 0003 at FFFFB1 (Check to see if Sonic has at least Three Chaos Emeralds</p><p>0003</p><p>00FF</p><p>FFB1</p><p>6C06 - Branch if Greater or Equal</p><p>4EF9 - Jump back to 01:9FD4</p><p>0001</p><p>9FD4</p><p>31FC - Move 000C to FFF762 (Set Higher Acceleration for Sonic)</p><p>0018</p><p>F762</p><p>4EF9 - Jump back to 01:9FD4</p><p>0001</p><p>9FD4</p><p>----------------------</p><p>*Restore Health between matches - Pit Fighter (World) (Rev A)</p><p></p><p>Target Offset</p><p>0CCB58</p><p></p><p>Enter this code at offset:</p><p>4EF9000DFC20 - (Jump to 0D:FC20)</p><p></p><p>33FC - Move D8 to FF2B7E (Set Full Health for Player 1)</p><p>00D8</p><p>00FF</p><p>2B7E</p><p>33FC - Move D8 to FF2C4C (Set Full Health for Player 2)</p><p>00D8</p><p>00FF</p><p>2C4C</p><p>52B9 - Add 1 to FF2EF8 (Go to Next level)</p><p>00FF</p><p>2EF8</p><p>4EF9 - Jump back to 0C:CB5E</p><p>000C</p><p>CB5E</p><p>----------------------</p><p></p><h3>(9).FAQ</h3><p>(Q): My code just crashed, what did I do wrong?</p><p>(A): Run a trace log just before the crash. Afterwards look towards the bottom of the page.</p><p></p><p>Most common crashes occur:</p><p>*When using JMP to go to the wrong location</p><p>*Using a Word command on a odd number. (0C79 0001 00FF 0001 is a code that WILL crash your genesis)</p><p>*An invalid opcode that cpu cannot register</p><p>------------------------------------------------</p><p>(Q):Is there more beyond what is in this tutorial?</p><p>(A):Oh yeah! Sprite replacements, Tilemaps, Bankswitching, Six Button Polling.</p><p>I won't cover some of this due to lack of understanding or difficulty explaining</p><p>certain topics.</p><p>------------------------------------------------</p><p>(Q):What advice can you give to new rom hackers?</p><p>(A):A few points, one backup files and document the things you find. You will be glad that you did.</p><p>Secondly, don't be afraid to experiment and break things and the last item of advice is don't be afraid to</p><p>set the work down and walk away.</p><p></p><p>I have walked away from many projects in frustration only to find the solution or fix first try after some time away.</p><p>------------------------------------------------</p><p>(Q): What if I don't have enough space to insert an JMP command?</p><p>(A): 4EF9 takes six btyes to accomplish. 4EF8 only needs four, however you are limited to 0000 - FFFF as a data rage that you can jump to.</p><p></p><p>It is a bit hacky but you can use 4EF801D0 and place your actual 4EF9 JMP command at offset 01D0. Now you may notice that this places you</p><p>Inside the game's header. 01D0 through 01EF aren't really used for anything so these small section of empty space can be used in a pinch.</p><p>The only catch is space is VERY LIMITED.</p><p></p><p>I got the idea looking through the code of Golden Axe II which uses code inside of its header.</p><p>------------------------------------------------</p><p>(Q): Why don't you use an assembler?</p><p>(A): Meh.</p><p>------------------------------------------------</p><p>(Q): Any chance we will see a SNES tutorial?</p><p>(A): Maybe, I'll think about it.</p><p>------------------------------------------------</p><p></p><h3>(A).Useful Links</h3><p>MarkeyJester’s Motorola 68000 Beginner’s Tutorial</p><p><a href="https://mrjester.hapisan.com/04_MC68/" target="_blank">https://mrjester.hapisan.com/04_MC68/</a></p><p></p><p>Game Genie and Ram Codes</p><p><a href="http://Gamehacking.org" target="_blank">Gamehacking.org</a></p><p></p><p><a href="https://plutiedev.com/" target="_blank">https://plutiedev.com/</a></p><p></p><p>ASM to Hex Reference</p><p><a href="https://info.sonicretro.org/SCHG:68000_ASM-to-Hex_Code_Reference" target="_blank">https://info.sonicretro.org/SCHG:68000_ASM-to-Hex_Code_Reference</a></p></blockquote><p></p>
[QUOTE="BillyTime Games, post: 6637, member: 12"] Hacking Games in Hex (Sega Genesis Edition) Dec. 9th 2024 BillyTime! Games -------------------- [HEADING=2](0).Intro[/HEADING] Welcome, this tutorial aims to ease newcomers and intermediates into hacking Sega Genesis games via a hex editor. You will need a few programs, this tutorial will assume that you are using the following *Gens r57 Shell Mod *Notepad++ *HxD I personally would like to thank Jlukas and Tony Hedstrom for giving me the tools and knowledge on how to modify my favorite games. My hope is to give back to the community and give you some of my knowledge to make some excellent rom hacks in the future. [HEADING=2](1).Starting Out, RAM Search, Breakpoints and Trace Logs[/HEADING] To start off, we will need Gens r57 Shell Mod. This is my preferred emulator of choice when coding. To start, we will be looking at World of Illusion Starring Mickey Mouse and Donald Duck (USA, Korea). The left hand window is our RAM Search, this will help us locate various address stored such as lives and whatnot. We are going to look for health to start off. We will search for equal to 1 change and have mickey take damage as seen here. We will repeat this process by taking another hit and searching for equal to 2 number of changes and so on and so forth. (This is the USA rom btw, addresses and locations get changed up slightly across revisions.) Eventually we will find that FFA038 is the ram address that stores mickey's health. Real quick, we will press Ctrl+G to open the cheat menu and enter FFA038:0500 as our code. In doing so, Mickey will essentially have Infinite health! The only problem is that this is a ram code and cannot be patched to a rom, for that we will need breakpoints! So first and foremost, we will disable our code. We will open our debugger under tools and click add. We will add FFA038 as our breakpoint and click enable and write. What will happen is that when FFA038 changes value, the game will stop and tell you what code in the game made the write to that ram address. So next step would be to click okay and go and take a hit. So after taking a hit, the game will stop and show you this code highlighted in green. This is the code that causes mickey to lose health when hit. 00:F098 9F 28 SUB.B D7,$0038(A0) So the best approach for this would be to use a branch. By using 00F098:6002 in you game genie menu, you can essentially give mickey infinite health! But real quick lets break down the branch routine. ------------------------------------------------ 60 is to tell the computer to branch regardless with no condition, useful for skipping over things and helps when designing master codes. 02 tells us to skip over two bytes which would mean skipping 00F098 and 00F09A. 6004 would cause a skip over F09C as well and probably isn't ideal. There are multiple branch conditions too, for example. 6702 - Branch if Equal 6602 - Branch if not equal 6C02 - Branch if Greater or Equal 6302 - Branch if Less than F08A also adds 1 to D7 which is subtracted from your health. You can also reach the same effect by using 00F08A:4E71 4E71 stands for NOP or No Operation. It skips over one byte. Using multiple of these could work when dealing with multiple bytes but its simpler to use a branch instead which took me time to grasp. ------------------------------------------------ By opening World of Illusion in a hex editor such as HxD, the results you came up with can be implemented with ease! Pressing Crtl+G will open up your offset menu. We are going to type in F08A and hit enter. When we enter our code, the text will be red to sigfnify that we made changes and have yet to save them. We will save as and create a new file for our new infinite health hack. Note, HxD creates a BAK file which is a back up of the previous revision which is helpful incase something goes incredibly wrong. So now our first hurdle.... So for this portion, I will introduce you to Trace Logs. By pressing Pause/Break on our keyboard when can halt emulation. It is advised when turning on Trace Logs as it records all machine code to TXT while active. I use Notepad++ when reading Trace Logs, it loads quickly and its easy to search and navigate, especially when we hit a break point and want to investigate the code further. We will pause our emulation, Hit Ctrl+Shift and R to reset. You should see a black screen sitting at 0 for your red counter. From there, we will go to tools, tracer tools and click trace. The we will unpause the emulation until the red screen appears and then pause again and turn off the trace. The last result is interesting as it branches due to A0 not being equal to D1. Those two numbers aren't quite important for what we are doing right now. So lets try 0004FC:4E71! Congrats on your first hack. That's pretty much the basics and how I make hacks. [HEADING=2](2).Addition and Subtraction[/HEADING] Next up is addition and subtraction. For this segment we will use Sonic 2 (Rev A) as our base. First we will collect a ring or two and check for greater than previous value in Ram Search. We will find eventually that FFFE21 is the ram address that affects rings. From here we will go to our Debugger and enter FFFE21 as our breakpoint, clicking enable and write. From here, we just simply collect a ring! 011FE0 is the code that will come up. 011FEA is also interesting but for different reasons. We will circle back. But lets look deeper into this opcode. Addq.w affects a Word address rather than a Byte address. What this means is that this code affects both FFFE20 and FFFE21 rather than just FFFE21 itself. With that said, word addresses should not be used on odd address numbers as the computer gets confused and locks up. For targeting odd number ram addresses, you will simple use a Byte address. So here is the opcode in Hex 52 78 - Add 1 (Target Word address) FE 20 - Target ram address Absolutely dead simple on how to change this. Change 52 78 to 54 78. Now sonic Collects double rings! To subtract, just as simple! Change 52 78 to 53 78. Even numbers add and odd numbers subtract. This opcode has a limit of 8 or so. However other opcodes exist to allow you to add or subtract more when needed. Moving over to 011FEA or more spefically 011FEC. 0064 is hex for 100, the amount of rings Sonic needs to gain and extra life. By changing this you can raise or lower the required rings needed for Sonic to earn an extra life. As a side note, it is a good idea to keep a record of the opcodes you come across and note its functions. When we get into custom coding, this will be a boon. A basic romhacking tool kit that will help you optimize development on any hacks or help with reference when you get stuck. [HEADING=2](3).JMP Command[/HEADING] So now we have JMP Commands or as I call them hijacks. This form of coding is about replacing or adjusting code to some free space in the rom and expanding on what is there. Lets continue with Sonic 2 and ram address FFFE21. Lets collect some rings first, then we shall set our breakpoint in the debugger. Then take a hit. This code should pop up. 01:2152 - MOVE.W $0000, ($FE20) The above code is responsible for Sonic losing all his rings when hit without a shield. It is six bytes and is perfect for a JMP hijack. The code will be using is 4EF9 ???? ???? where the ? will be filled in with the offset in hex we plan to jump to. Make some free space at the end of the rom to point our code to offset 00100000. So our hijack will look like this. 012152:4EF9 012154:0010 012156:0000 ------------------------------- I like to bookmark the line above with what the code is supposed to do, it helps with locating code faster in case something goes wrong and needs immediate troubleshooting. Here is the line of code you will use. 0C 79 00 14 00 FF FE 20 6C 0C 31 FC 00 00 FE 20 4E F9 00 01 21 58 04 78 00 14 FE 20 4E F9 00 01 21 58 Okay, that looks complicated.... Lets break it down and detail what everything does. 0C79 - CHECK FOR AT LEAST 20 (Hex) RINGS 0014 00FF FE20 6C0C - BRANCH IF GREATER OR EQUAL ----------------------------> BRANCH JUMPS OVER THIS CODE 31FC - CLEAR ALL RINGS 0000 FE20 4EF9 - JUMP BACK 0001 2158 ----------------------------- 0478 - SUBTRACT.W 0014 (20) FROM FFFE20 0014 FE20 4EF9 - JUMP BACK to the next opcode 0001 2158 By using this hijack and the above code, Sonic now only loses 20 rings per hit! As an added check sonic will be set to zero rings if he already has 20 or less rings. That way there aren't any added side effects such as ring overflow. ------------------------------- Don't forget that you will need a master code for this particular game, not all games have master codes. 00031A:602E [HEADING=2](4).Button Mask and Cheat Codes[/HEADING] Continuing with Sonic 2, We are going to locate the Ram Address for Button Inputs and create a JMP hijack to create a simple cheat code. To start In RAM Search without pressing any buttons, we are are going to search for equal to value 0. Press and hold the B button and pause the emulation. Now search Not Equal to value 0. Eventually the top RAM address will be FFF604 which I call a button mask. When controllers are polled, it is sent to a RAM address which can be used for reference by the game later. Just about all polling is the same so here are some handy values to look for when searching for a button mask. 40 - A Button (No other buttons pressed) 10 - B Button (No other buttons pressed) 20 - C Button (No other buttons pressed) C0 - A Button + Start 90 - B Button + Start A0 - C Button + Start Next, we are going to lose some lives, searching either less than previous value or by searching for number of changes. Eventually FFFE12 will come up as our RAM address. From here, we will reset and return to the title screen. Set FFFE12 as your breakpoint and start you game. The breakpoint will trigger and this opcode will pop up. 003C76 move.b #$03, ($FE12) The code here sets Sonic's Lives to 3. If we want we can always change this number to start Sonic with more lives as an added bonus. But to Stick with our Lesson, we will use a JMP command from before in combination with our new button mask that we found. FFFFB1 is our target RAM address. By setting FFFFB0:0007 in your game genie window, it is possible to give Sonic all Seven Chaos Emeralds! Granted this can be done through a cheat in the game's sound test in the options menu, our method will be a lot quicker. We will do this by checking to see if the B button is being held when pressing start at the title screen. If it is, Sonic will recieve all seven chaos emeralds at once! So if you still have the modded file with our ring subtraction code, we can continue to build upon our previous work. 003C76:4EF9 003C78:0010 003C7A:00A0 ------------------------------- 11FC - Set Sonic's Lives to 3 0003 FE12 0C39 - Check if B is being held when starting game 0090 00FF F604 6606 - Branch if Not Equal 11FC - Give Sonic all 7 Chaos Emeralds 0007 FFB1 4EF9 - Jump Back 0000 3C7C ------------------------------- That Seemed a bit too easy. Lets expand up this code and add an extra cheat code! ------------------------------- 11FC - Set Sonic's Lives to 3 0003 FE12 0C39 - Check if A is being held when starting game 00C0 00FF F604 660C - Branch if Not Equal 11FC - Give Sonic 50 lives 0032 FE12 4EF9 - Jump Back 0000 3C7C 0C39 - Check if B is being held when starting game 0090 00FF F604 6606 - Branch if Not Equal 11FC - Give Sonic all 7 Chaos Emeralds 0007 FFB1 4EF9 - Jump Back 0000 3C7C ------------------------------- If you notice, our emerald code isn't working. Turns out the there is a small line of code that is overriding our cheat code. This can be found by setting a breakpoint at FFFFB1 and starting the game. This line should pop up 003CE8 move.w D0,($FE16) What is happening is that D0 had value Zero and is being placed into various ram addresses, effectively cleaning them out. To keep the game from clearing our stolen emeralds, we will use this code. 003CE8:6002 Everything should work as intended now, you can always check the ram addresses to see if the code immediately worked or play around and find out in game. You could also do both! This type of hacking can be pretty rewarding as you can make new cheat codes to have fun with the game in new ways, add them to games that never had cheats or make a game more accessible to someone who struggled to play it before. Next up is going to be fun and a lot trickier. We will be covering SRAM! [HEADING=2](5).SRAM[/HEADING] Here we will cover how to use SRAM to Save and Load values for future use. The possibilities are endless when using SRAM. You can Save progress, High Scores, even unlockable characters if you so wish. For this section, we will be using Shinobi III - Return of the Ninja Master (USA) as our example. To get started go to offset 01B0 in your hex editor and paste this line in HxD with Ctrl+B FF FF 52 41 F8 20 00 20 00 01 00 20 02 00 20 20 This line is part of the game's header that will tell the system that SRAM is being utilized. Next up is our game's level modifier. We will be running a write breakpoint in the debugger. FF37A6 Next some initial setup, we will be using the game's level select code and replacing it in favor of a load menu. Let start by enabling level select. Enable Level Select: 00B67E:4E71 Now lets play with the breakpoint on until we reach stage 2. The game will stop and throw up this code. 00B0FA:5239 - Add 1 to 00FF37A6 (Go to next stage.) There is enough room to use a code hijack here. Perfect for what we need. Here is the following code to save your progress, annotated to explain each function. Save Code 00B0FA:4EF9 - JMP to 000FF2B0 00B0FC:000F 00B0FE:F2B0 0FF2B0:5239 - Go To Next Level 0FF2B2:00FF 0FF2B4:37A6 0FF2B6:41F9 - Move 00FF37A6 to A0 (Level Modifier goes here) 0FF2B8:00FF 0FF2BA:37A6 0FF2BC:13FC - Move.b (Enable SRAM) 0FF2BE:0001 - 01 (Enable SRAM) 0FF2C0:00A1 - 00A130F1 (Enable SRAM) 0FF2C2:30F1 - 00A130F1 (Enable SRAM) 0FF2C4:43F9 - LEA (start of SRAM) 0FF2C6:0020 - ($00200001),A1 (start of SRAM) 0FF2C8:0001 - ($00200001),A1 (start of SRAM) 0FF2CA:1010 - move A0 to D0 (Move Level Modifier Value to D0) 0FF2CC:0189 - MOVEP.W D0,#$0000(A1) (Move D0 number into sram) 0FF2CE:0000 - (move D0 number into sram) 0FF2D0:13FC - MOVE.B #$00,($00A130F1) (Disable SRAM) 0FF2D2:0000 - (Disable SRAM) 0FF2D4:00A1 - (Disable SRAM) 0FF2D6:30F1 - (Disable SRAM) 0FF2D8:4EF9 - JMP back to 00B100 0FF2DA:0000 0FF2DC:B100 SO what happened here is that we set A130F1 to 01. This is how we enable SRAM. When this code is active. SRAM code appears at the 2MB mark so we always need to make sure our code is below offset 1FFFFF in order to work. Otherwise our code will only serve to crash the game. We set it back to 00 afterwards to prevent SRAM from always being active. We only need to it for this purpose anyways. NOTE: From plutiedev, it is not really reccomended to use $00200001 in case of a power failure. Also, a checksum comes in handy when dealing with something like high scores to prevent a game from crashing or bugging out if the is no or corrupt SRAM. Now with the level select active, keep the write breakpoint active on FF37A6 and press start to pause the game and press C the game will throw up this code. 00B6AA:13C0 - Move D0 to 00FF37A6 We don't want this code constantly active each frame so we will just NOP it out. Disable Level Selection: 00B6AA:4E71 00B6AC:4E71 Let scroll up a bit, where did that number in D0 come from. Move up to 00B6A4 and there is our answer! 00B6A4:1039 Move 00FF37A6 to D0. This is the perfect spot for our hijack! Here is the following code to Load your progress, annotated to explain each function. Load Code: 00B6A4:4EF9 - JMP to 000FF300 00B6A6:000F 00B6A8:F300 0FF300:41F9 - Load Level Number to A0 (Level Modifier goes here) 0FF302:00FF 0FF304:37A6 0FF306:13FC - Move.b (Enable SRAM) 0FF308:0001 - 01 (Enable SRAM) 0FF30A:00A1 - 00A130F1 (Enable SRAM) 0FF30C:30F1 - 00A130F1 (Enable SRAM) 0FF30E:43F9 - LEA (start of SRAM) 0FF310:0020 - ($00200001),A1 (start of SRAM) 0FF312:0001 - ($00200001),A1 (start of SRAM) 0FF314:0109 - MOVEP.W #$0000(A1),D0 (Load SRAM into D0) 0FF316:0000 - (Load SRAM into D0) 0FF318:1080 - (Move D0 to A0) (Move D0 to Level Modifier) 0FF31A:13FC - MOVE.B #$00,($00A130F1) (Disable SRAM) 0FF31C:0000 - (Disable SRAM) 0FF31E:00A1 - (Disable SRAM) 0FF320:30F1 - (Disable SRAM) 0FF322:4EF9 - JMP to 0000B6AA 0FF324:0000 0FF326:B6AA So if you have followed along up until this point, congrats! You just recreated one oif my earliest hacks! Shinobi III SRAM. Here are the instructions on how to use it. Saving: Game saves after every level past the first round. Loading: On Stage 1, Pause your game and press C, a number will pop up indicating what round you left off at. Unpause to load your game. Be sure to fix your checksum afterwards. You can do so with this tool in the link below. Its an older tool so it detects BIN extentions instead of MD. [URL unfurl="true"]https://www.romhacking.net/utilities/342/[/URL] [HEADING=2](6).Palettes[/HEADING] Under tools, you can select VDP ram to see when certain GFX are loaded in as well as view the current loaded palettes. There are 4 lines of 16 colors. Certain colors can be manipulated at and during run time but what we are going to do is change colors on a more permanent basis. We will Use Ghostbusters (World) (v1.1) as our base. Go into a stage and Select Tools, VDP Ram, from there click Copy Pal and open Notepad. Then hit Ctrl+V and you will be given this bit of code. 000 000 EEE 46C 68E 8AE 222 844 C86 ECA 24A 0EE 08E 04E 00A 026 000 000 EEE E60 EA0 EE4 CAE 86E 22E 44A 4EC 0E0 0A0 060 888 444 000 000 000 AEE EEE ECC CAA A88 866 644 422 A44 000 000 000 000 000 888 AAA EEE 022 244 466 688 002 204 422 644 004 026 248 000 this here represents the numbers associated with each 16 colors across four lines. 000 is black, EEE is white and so on. The first line is our point of interest as this is the line used for the Ghostbuster's uniforms. Open your Ghostbusters rom in HxD and search for 000 000 EEE 46C 68E 8AE 222 844 C86 ECA 24A 0EE 08E 04E 00A 026 in hex. Match not found! Wait, what?! Turns out something is missing.... so this time add a zero to the begining of each number. Your code will look like this. 0000 0000 0EEE 046C 068E 08AE 0222 0844 0C86 0ECA 024A 00EE 008E 004E 000A 0026 Now we have found our palette at offset 01:BE3E Lets replace this line with the following code by using Copy followed by Ctrl+B in HxD: 0000 0000 0EEE 046C 068E 08AE 0222 0224 0228 044C 024A 00EE 008E 004E 000A 0026 If you boot the game up now, you will see that in Ghostbusters have Red Uniforms in game! This is one of many ways to maniulate palettes to give games a fresh coat of paint. Alternatively you can open offset 01:BE3E in Hivebrain and edit colors without tweaking numbers can get a better visual representation of what your colors will look like. [HEADING=2](7).Address and Data Registers[/HEADING] So this next part will be a bit tricky to explain but bear with me. The Genesis has eight address registers and eight data registers, A0 - A7 and D0 - D7. A7 is normally used as your stack pointer which normally for me means I don't use it so things don't crash unexpectedly. Everything else is usually fair game. Address registers help with locating damage values (SOR2), art pointers (Ghostbusters), level tables (Earthworm Jim) and whatnot. Data registers usually deal with simple math or moving around time sensitive data. Lets use Streets of Rage 2 as an example of how both address registers and data registers are used in calculating damage done to enemies. Run a trace log at the start of Stage 1 while playing as Axel and drop kick the first enemy you see while the trace log is active. Afterwards in Notepad++ open your trace log and Search (Ctrl+F) for 00:545C. You will find the following snippet of code. 00:545C 30 2A MOVE.W $008E(A2),D0 A0=00013DAA A1=00013E70 A2=FFFFF500 A3=FFFFEF00 A4=001F10E6 A5=FFFFEE00 A6=FFFFEC80 A7=FFFFFFEE D0=00C80018 D1=FFFE0000 D2=000100D8 D3=FFFF0000 D4=00000002 D5=405CFF00 D6=00D100C4 D7=00C90000 xnZvc 00:5460 91 6A SUB.W D0,$0080(A2) A0=00013DAA A1=00013E70 A2=FFFFF500 A3=FFFFEF00 A4=001F10E6 A5=FFFFEE00 A6=FFFFEC80 A7=FFFFFFEE D0=00C80008 D1=FFFE0000 D2=000100D8 D3=FFFF0000 D4=00000002 D5=405CFF00 D6=00D100C4 D7=00C90000 xnzvc Lets break it down. At 00:545C FFF58E is moved in to D0, we get this number by adding 8E to FFFFF500 which is located in A2 (Address Register 2). From there, D0 (D0=00C80008) is Subtracted from FFFFF580 (Galsia's Health), this address is found in the same way. In this instance D0 is only using the last four digits (0008) from there we can conclude that Axel's drop kick does eight points of damage to an enemy. Using the XP System Example Code listed below, damage values can be manipulated to be increased or decreased depending on who is getting hit as well adding extra conditionals such as damage values based on player score. [HEADING=2](8).Example Code[/HEADING] *XP System - Streets of Rage 2(USA)* Hijack Target Offset 00545C Enter this code at offset: 4EF9001FFD00 (Jump to 1F:FD00) Damage Routine (1F:FD00) B5FC - Check if Player 1 has been hurt (Compare A2 for FFFFEF00) FFFF EF00 6606 - Branch if not equal 4EF9 - Jump to Defense code (Jump to 1F:FE00) 001F FE00 B5FC - Check if Player 2 has been hurt (Compare A2 for FFFFF000) FFFF F000 6606 - Branch if not equal 4EF9 - Jump to Defense code (Jump to 1F:FE00) 001F FE00 302A - Load Damage (MOVE.W $008E(A2),D0) 008E 0C2B - Check score (100,000 Points) *Compare 09 at $0096(A3) (FFEF96 or FFF096)* 0009 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (200,000 Points) *Compare 19 at $0096(A3) (FFEF96 or FFF096)* 0019 0096 6302 5240 0C2B - Check score (300,000 Points) *Compare 29 at $0096(A3) (FFEF96 or FFF096)* 0029 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (400,000 Points) *Compare 39 at $0096(A3) (FFEF96 or FFF096)* 0039 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (500,000 Points) *Compare 49 at $0096(A3) (FFEF96 or FFF096)* 0049 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (600,000 Points) *Compare 59 at $0096(A3) (FFEF96 or FFF096)* 0059 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (700,000 Points) *Compare 69 at $0096(A3) (FFEF96 or FFF096)* 0069 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (800,000 Points) *Compare 79 at $0096(A3) (FFEF96 or FFF096)* 0079 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 0C2B - Check score (900,000 Points) *Compare 89 at $0096(A3) (FFEF96 or FFF096)* 0089 0096 6302 - Branch If less 5240 - Add 1 to damage (Add 1 to D0) 916A - Subtract Damage (SUB.W D0,$0080(A2) - Subtract D0 from $0080(A2) or FFF580 as an example which is an address for enemy health.) 0080 4EF9 - Jump back (Jump to 00:5464) 0000 5464 Defense Routine (1F:FE00) 302A - Load Damage (MOVE.W $008E(A2),D0) 008E 0C2B - Check score (100,000 Points) *Compare 09 at $0096(A3) (FFEF96 or FFF096)* 0009 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 19 at $0096(A3) (FFEF96 or FFF096)* 0019 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 29 at $0096(A3) (FFEF96 or FFF096)* 0029 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 39 at $0096(A3) (FFEF96 or FFF096)* 0039 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 49 at $0096(A3) (FFEF96 or FFF096)* 0049 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 59 at $0096(A3) (FFEF96 or FFF096)* 0059 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 69 at $0096(A3) (FFEF96 or FFF096)* 0069 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (100,000 Points) *Compare 79 at $0096(A3) (FFEF96 or FFF096)* 0079 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 0C2B - Check score (900,000 Points) *Compare 89 at $0096(A3) (FFEF96 or FFF096)* 0089 0096 6302 - Branch If less 5340 - Subtract 1 to damage (Sub 1 from D0) 916A - Subtract Damage (SUB.W D0,$0080(A2) - Subtract D0 from $0080(A2) 0080 4EF9 - Jump back (Jump to 00:5464) 0000 5464 ---------------------- *Faster Acceleration - Sonic The Hedgehog 2 (World) (Rev A) Target Offset 19FCE Enter this code at offset: 4EF900100040 - (Jump to 10:0040) Routine: 31FC - Move 000C to FFF762 (Set Normal Acceleration for Sonic) 000C F762 0C39 - Compare 0003 at FFFFB1 (Check to see if Sonic has at least Three Chaos Emeralds 0003 00FF FFB1 6C06 - Branch if Greater or Equal 4EF9 - Jump back to 01:9FD4 0001 9FD4 31FC - Move 000C to FFF762 (Set Higher Acceleration for Sonic) 0018 F762 4EF9 - Jump back to 01:9FD4 0001 9FD4 ---------------------- *Restore Health between matches - Pit Fighter (World) (Rev A) Target Offset 0CCB58 Enter this code at offset: 4EF9000DFC20 - (Jump to 0D:FC20) 33FC - Move D8 to FF2B7E (Set Full Health for Player 1) 00D8 00FF 2B7E 33FC - Move D8 to FF2C4C (Set Full Health for Player 2) 00D8 00FF 2C4C 52B9 - Add 1 to FF2EF8 (Go to Next level) 00FF 2EF8 4EF9 - Jump back to 0C:CB5E 000C CB5E ---------------------- [HEADING=2](9).FAQ[/HEADING] (Q): My code just crashed, what did I do wrong? (A): Run a trace log just before the crash. Afterwards look towards the bottom of the page. Most common crashes occur: *When using JMP to go to the wrong location *Using a Word command on a odd number. (0C79 0001 00FF 0001 is a code that WILL crash your genesis) *An invalid opcode that cpu cannot register ------------------------------------------------ (Q):Is there more beyond what is in this tutorial? (A):Oh yeah! Sprite replacements, Tilemaps, Bankswitching, Six Button Polling. I won't cover some of this due to lack of understanding or difficulty explaining certain topics. ------------------------------------------------ (Q):What advice can you give to new rom hackers? (A):A few points, one backup files and document the things you find. You will be glad that you did. Secondly, don't be afraid to experiment and break things and the last item of advice is don't be afraid to set the work down and walk away. I have walked away from many projects in frustration only to find the solution or fix first try after some time away. ------------------------------------------------ (Q): What if I don't have enough space to insert an JMP command? (A): 4EF9 takes six btyes to accomplish. 4EF8 only needs four, however you are limited to 0000 - FFFF as a data rage that you can jump to. It is a bit hacky but you can use 4EF801D0 and place your actual 4EF9 JMP command at offset 01D0. Now you may notice that this places you Inside the game's header. 01D0 through 01EF aren't really used for anything so these small section of empty space can be used in a pinch. The only catch is space is VERY LIMITED. I got the idea looking through the code of Golden Axe II which uses code inside of its header. ------------------------------------------------ (Q): Why don't you use an assembler? (A): Meh. ------------------------------------------------ (Q): Any chance we will see a SNES tutorial? (A): Maybe, I'll think about it. ------------------------------------------------ [HEADING=2](A).Useful Links[/HEADING] MarkeyJester’s Motorola 68000 Beginner’s Tutorial [URL]https://mrjester.hapisan.com/04_MC68/[/URL] Game Genie and Ram Codes [URL='http://Gamehacking.org']Gamehacking.org[/URL] [URL]https://plutiedev.com/[/URL] ASM to Hex Reference [URL]https://info.sonicretro.org/SCHG:68000_ASM-to-Hex_Code_Reference[/URL] [/QUOTE]
Insert quotes…
Verification
Post reply
Community
Tutorials & Guides
Hacking Games In Hex (Sega Genesis Edition)
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.
Accept
Learn more…
Back
Top