News:

11 March 2016 - Forum Rules

Main Menu

Sega Genesis / Megadrive Shadowrun Help

Started by bycrom333, March 08, 2023, 07:19:17 AM

Previous topic - Next topic

bycrom333

Hello!

I'm new to the scene, this is my first ROM hack. I'm working on a patch that allows you to choose one of three female characters as your starting character instead of Joshua. Work has gone well, I've figured out everything except for one thing.

So, having stolen the images for Ilene, Rianna, and Freya for the possible main character images, I thought it would be fun to replace those characters with the different versions of Joshua. So when you walk into Matchsticks to hire Rianna, for example, there is decker Joshua instead. So I switched all the appropriate data and it works... almost. When you talk to them, it's Joshua's portrait. When you hire them, it uses the correct sprite. But, before you hire them, the sprite you see standing in the bar is the old female sprite corresponding to the original character (Ilene, Rianna, or Freya).

Here's where I'm at...

The data as for what sprite to display in the setting (the bars) does not seem to be anywhere near the address of the characters' stats.

I have an emulator with debug features. Is there a way for me to see where the game is looking up the sprite data as I enter a location? As I said, I'm really new to this.

If it is using the same data as when you have the character, I even know what value the bit needs to be set at. (Rianna uses the sprite value of 06, for example, while Joshua is 03.) I just can't find the address.

Let me know if you can give me a nudge in the right direction!

FAST6191

Most consoles will load the data from the ROM to VRAM and then use whatever (most consoles further splitting between backgrounds used for backgrounds and most text, and sprite memory/object area memory, or in the case of the megadrive) to manipulate its position on screen.
https://www.copetti.org/writings/consoles/mega-drive-genesis/#graphics

If you wanted to change it and more primitive (but simpler) methods have failed you, as they appear to have here, then you would probably start outside the bar, open up a VRAM viewer/tile viewer in your emulator (set to update/refresh) and walk in, it will then load up the tile(s) and you can take note of where they land. From there you can set a break on write (bpw in most emulators) in whatever we are suggesting as a megadrive/genesis debugging emulator to said location, then either revert to an older savestate or hope leaving and entering again does the deed.

You would then have some kind of read (don't know if CPU based, DMA based or something else) from an area of the ROM to that area which the debugger should show you. From here you get to edit pointers to display whatever you like, or if it is some kind of calculation that derives the image you care about (recruited/available/not, I don't know what this game does but sounds like a possibility and might well be in another) then twist that to be something else (how a lot of play as boss/npc/hidden character hacks or change enemy hacks work)

bycrom333

Ugh. I spent a couple hours trying to figure this out today and just failed. Is there a tutorial or online guide for beginners for doing debugging stuff? I'm using Exodus for my Genesis emulator and I can't find any documentation or guides or videos to help me out. I'm willing to learn but I'm such a newb I feel like I should probably start with the basics.

FAST6191

Most people do ramp up to fiddling with assembly unless they wander in with suitable background knowledge otherwise, some have jumped right in but it is not like other things people do for hobbies or in schools.
To that end learn to make cheats, learn to edit text (sounds like you are there), learn enough to fiddle with tile viewers (likely not too far out here), maybe get enough to figure out level formats and stats (both benefit immensely from debugging approaches but are far from impossible without it) and then a lot of assembly falls into place.

There are a variety of guides out there, how many will be megadrive centric I don't know.

https://fceux.com/web/help/Debug.html is the gold standard for console debugging that everything else is measured against. Only things to challenge it are the PC debuggers pushed wider (see stuff like interfacing IDA, ghidra or radare2 with emulators and GDB bridges).

https://www.romhacking.net/documents/361/ is for the GBA as well as an odd UI emulator compared to most but the principles go wide.

Assembly can also be hard to learn. Not much out there today will teach you 68000/68K assembly and instead it is mostly going to be PC (X86) and ARM if there is anything. You might get something from a vintage book but at the same time that is fraught with peril as you might not get an appreciation for some of the more modern approaches taken.
https://www.randallhyde.com/AssemblyLanguage/www.artofasm.com/index.html for the first few chapters at least. https://stuff.pypt.lt/ggt80x86a/asm1.htm gets there a bit quicker but also suffers for being more condensed.
https://www.youtube.com/watch?v=ktfIkfNz99Y as a series if video formats are the way.
Such things will see you steeped in all manner of computing quirky concepts that come home to roost at all sorts of odd times, even more so if you are going down the self taught path so things like https://www.youtube.com/playlist?list=PL96C35uN7xGLLeET0dOWaKHkAlPsrkcha also become relevant.


Generally though.

Computer memory/security/operating principles are that memory has three things it can do.
1) Be written to
2) Be read from
3) Have code executed upon it

Some combine things into access but eh.

Accordingly there are three main breakpoint types in emulators that form the backbone of debugging.

1) Break on write (BPW in most emulators/debuggers)
2) Break on read (BPR in most emulators/debuggers)
3) Break on execute (BPE and sometimes BOE)

These will halt emulation in the event that the action in question touched the memory and say this is what did the deed, here are the contents of instructions and in the case of modern things here are the last 10 or instructions executed (older stuff might not, though https://www.youtube.com/watch?v=WH3ja70_okA is still one of the better examples of a workflow/mindset I have seen).
The trick is getting something that will be changed by the thing you want. If you can get close right off the bat then great, if you have to note that audio channel whatever is changed after this event (say playing a sound effect) or have to filter out the various reads of the controller state then so it goes. Close usually comes as a result of other assembly work or cheats (want to make an infinite health cheat then setting a break on the thing writing to the cheat's destination, or possibly reading from it to determine if you are dead or not, is generally a good plan rather than going all the way to seeing when a death animation sprite is written to VRAM and working back from there). Working backwards to something being called tracing. Moving one instruction on at a time being referred to as stepping.

If you are not familiar with cheats and the making thereof then get so as a first course of action.
https://doc.kodewerx.org/ https://web.archive.org/web/20080309104350/http://etk.scener.org/?op=tutorial covering that quite well.

Assembly looks complicated with all the instructions and quirks, and it certainly can be, but few memorise all the instructions (not to mention many are minor variations on other concepts as computers are particularly dumb devices) I usually break it down into three main camps and once you get a bit more familiar you can skip over things to just retain the general flow.
1) Maths. Addition, subtraction, multiplication, division (though not necessarily on all processors as fractional numbers are not fun), boolean logic, shifts, rotates, things you will find in a guide to advanced spreadsheet operations ( https://help.libreoffice.org/latest/ro/text/scalc/01/04060106.html )...
2) Housekeeping. So you have say 8 16 bit registers several of which are not general purpose. Not enough to do anything like even a game at the time so things get shuffled around them. On any new processor then first thing I learn is usually what the mov (typically copies one register to another, or sometimes a memory location or immediate value/value in the instruction itself) and push/pop, as well as memory reads and writes if available to the CPU (some rare things will be DMA only).
3) Program flow. Maths and fiddling with the CPU is fun and all but when games might well literally be defined as a series of interesting decisions (not all programs make them, some might just add two rows of numbers together and need no smarts at all, indeed most early programs people make are this aka basic procedural programs) then you need options to make decisions based on previous input, events, calculations and the like. This is why any programming guide will take great pains to teach you about loops. https://www.tutorialspoint.com/cprogramming/c_loops.htm . Assembly naturally has this sort of thing as well, though tends to be different names for the steps involved (compare and then branch/jump for IF ELSE, WHILE tending to be something with a timer or adding one to a counter each loop around, FOR EACH then being a kind of merge of the two previous things as you repeat something over a larger area).

Some emulators will have more advanced tricks, conditional breakpoints (tell me if it is written to but only if in this range) and the like, some will be more basic (some debuggers I have used in the past only featured a breakpoint called run to line which is a special case of break on execute). FCEUX's trace logger being a good example of an advanced trick that can save a lot of hassle -- it will tell you what the last new executed piece of code is which is great if you want to learn say about jumping and then go idle in a corner, walk around, punch... everything but jump and then jump. Saves having to fiddle with sprite locations, sprite types, work backwards from sound effects, work forwards from button presses and the like.
Most will also feature memory viewers (maybe as part of cheat makers), tile viewers (easy to see what particular tiles are changed if you need that), register viewers (registers as well as a thing in the CPU are also a term for areas of memory that handle the other aspects of hardware like audio, graphics, controllers, cartridge reads and more besides) and disassemblers so you can turn binary data into human readable instructions (with the perk of possibly also knowing what the state of the CPU and memory is, as well as location of the code that might even be decrypted and uncompressed if that is a thing for your machine, something you don't have if doing it on a whole ROM you encountered just now).

Anyway I am rewriting guides I have done in more depth before and probably exist in more depth elsewhere with nice pictures and video if you want that so I will tie it off there.

bycrom333

Thank you for the in-depth reply! I will start looking through the resources you linked and see what I can make of them.

In terms of my skill level, I know my way around a hex editor, so I know how to change existing text slightly as long as there is no compression. (Another game I was looking at had a Huffman code, and I can't make heads or tails of how that works.) I don't know how to add text (no experience at all with pointers(?)) but I know how to change some values. So in the ROM hack I was working on, I successfully changed the starting character's portrait, in-game sprite, name, and stats. I also adjusted the dialogue through the whole game to compensate that the main character is now a female elf instead of a male human.

I encountered a slight hiccup in that when you saved and reloaded the game, the main character's original portrait would be restored, so I looked through another person's ROM hack who did something similar to see where the address was for the load game data / routine and I was able to fix that, too.

Exodus seems really powerful in terms of what it can do. It could pull up the VRAM, give a sprite list, etc. etc. But my skill level is preventing me from using any of that information to figure out where in the game code it is telling the machine which sprite to display. I feel like someone with even a little bit more experience could figure out my problem right away. I was able to set a breakpoint but it seemed like it was pointing me in the wrong direction, or maybe I just didn't understand what I was seeing. I did step through a bit but I didn't understand any of the opcodes so that didn't help.

But again, thank you for the in-depth reply! I will continue mucking about and maybe eventually I will get it. I appreciate you being patient with me!

FAST6191

On compression then despite the name the following does give a nice enough overview on the matter if you wanted a start
https://ece.uwaterloo.ca/~ece611/LempelZiv.pdf

Pointers I usually liken to the contents page of a book and are used mainly as calculating locations of things is resource consuming, especially when things are not likely to change (the Read Only part of ROM speaking to that one).
In older systems where you can see the cartridge in memory then pointers are likely to be of a style that goes with that (pointers being there to avoid calculations all the time after all). For the megadrive this is going to be fairly plain for most games as it is pretty much all there in memory. For other consoles where only a small window/page/mapped section/bank (terminology changes between console but means much the same thing) of the ROM is visible then that will be what is played to. For consoles that fetch files and stick them in memory to operate (DS on up for handhelds, most things based on CD/optical, floppy disc and possible some aspects of tape then things tend to become file level affairs as theoretically you don't know where you are going to land in RAM for any given compile (and later run itself) but you do know the file format so actually calculations are back, but life tends to be easier still for the hacker.
Equally while contents page of a book might speak to chapters as a whole then many games will need pointers per line/use pointers to end/start lines. Either way much like yanking a bunch of pages out of a book or stuffing new ones in will make the page counting computer get out of line with reality of what is on the original contents then so will changing lengths inside a game. Your job as hacker then becomes to put what you broke correct, sometimes you get lucky and the end of section has a nice 00 that is not otherwise in the text and you can search for that, note all the new locations and with a few flicks of a spreadsheet or something generate a new set of pointers. Other times you will have to go painstakingly through the game and recalculate things accordingly, or more likely recalculate every time you change something by having the text editor tool you made do it for you.

Finding sprites with debuggers (either because you can or because the simpler methods failed you).
So the sprite you want is on screen.
You open up the VRAM viewer and note where it is in VRAM (if the system supports several dozen tiles then you are going to want to narrow it down to the things you care about). Chances are it will be there every time (dynamic stuff did not come/get popular until a bit later in history) so you take note of where it is.
You then set a break on write to that particular area (or hold off for when it becomes more useful).
As it is already in memory then likely not much is going to happen.
You then want to watch the insertion into VRAM.
Maybe you are lucky and can trigger a cutscene that sees it swapped out and back in, maybe entering/leaving an area does something (there is a reason it fixes graphical and audio glitches for many things).... the easiest is likely to be starting the game and maybe loading a normal save (savestates have the problem of things potentially already being there, unless you know it is not there in which case you can save a few seconds).
Anyway so now it writes it to VRAM. Your breakpoint should say hold up something has been written to the area you told me to watch, here are the last 10 instructions or whatever that came before that. Said something doing the writing might be a dumb instruction that is the result of something (if this was say health and if you want to make an infinite health cheat then disabling the write new value command is great, for understanding the damage system then rather less useful), or might be something longer.
CPUs tend to want to be able to read and write to the larger memory and will have instructions for this. However it was soon seen that having your CPU being occupied by shuffling data around is a waste of potential, instead most systems then gained DMA (Direct Memory Access) options where the CPU can fire off some instructions to somewhere else in memory that will dutifully copy however much from one place to another without bothering the CPU and possibly faster than it as well.
You then get to find where in the ROM the data you want was fetched from and are looking at one of those commands. Main exception tends to be compression which for many things will decompress into normal RAM and then copy to VRAM. In that case you have both the compression algorithm to ponder (fortunately you have a working example of it right there) and where it fetched the data. Rinse and repeat the earlier part on data being where you want it to be but for this new location instead. Rinse and repeat that whole process until you land back at a read to somewhere in the ROM.

Alternatively you could go forwards if you figure out a trigger. For instance if you want to know about jumping then you might find for a given game that button A does one. You could tell the emulator to watch for something reading the control register and seeing what goes for something that detects A being pressed (granted the control register is probably copied, debounced to use proper parlance, into normal memory and the A being pressed is more likely to be a mask/boolean operation and then something, or maybe an interrupt (checking all the time with the CPU is boring/waste of resources, having something that will step in when it detects a condition it wants happens is better). Harder for a sprite searching effort to do something like this but you might find something or have an approach that works.

Opcodes are many and not necessarily obvious (at the time of the original assembly language setups then space was at a premium and it seems newer stuff continued the trend) and if you don't know what you are looking for then yeah it will seem a mountainous task. You will learn to filter it out a bit as you get better, though as a start you are looking for those CPU or DMA reads to the cartridge area of memory. The assembly debuggers will tend to give you a nice readable version of the destination if it is not immediately obvious from the instruction. Much has been found by basic breakpoint, nothing of interest so set new breakpoint to the earliest instruction on the list given by the previous breakpoint, repeat until ROM area read or something like that. You will likely miss a subtlety somewhere in the code and its handling of the data by doing this compared to understanding the steps (and greater meaning/collective meaning of them -- reading A is fine but you are not going to want to do up and A, left and A, A and B and all the rest* hence the boolean thing acting as a mask in the section above, understand the greater concept and the little stuff becomes so much means to an end) but we deal heavily in results so if it lands you in the right ROM location nobody is going to complain.

*indeed the games that specifically require nothing to be pressed to activate something feel very stilted (can't walk and shoot, lose all my speed when I unpause...) and many a ROM hacker has added in multi button efforts when encountering such a thing in the wild.