Kodewerx

Our culture has advanced beyond all that you could possibly comprehend with one hundred percent of your brain.
It is currently Sat Jan 25, 2020 8:14 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 16 posts ] 
Author Message
PostPosted: Sun Mar 22, 2009 3:22 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
I used that code in the enhacklopedia to riase the code generator memory editor's maximum goto address to the 807fffff range, which is where the code generator's ram data is, and found the active codes for searches there.
I went in memory editor, set 40 unused ram variables to equal a large number(F1F1), and then did a known 16-bit search on this in the code generator.
The first 40 were the unused ones I edited, and I made them all active codes, then went to the area I found the stored search codes, which is also right under where the active codes are(seriously, there is literally NOTHING between these two sets of data).

There's a number right before all the active search codes, telling how many active codes there are.
The limit is 40 on the code generator, but here you can set it higher than that, and just write codes over the search results, and it'll take effect in-game right after. That's right- I had fortee-ONE codes on in the code generator's active codes list.

If this number can be 16-bit, you might be able to have hundreds of codes applied here, and if you don't do a code search, all the active codes remain intact here even after you turn off the gameshark.

All you'd have to do is turn the code generator on, and have a code that sets the active codes number variable to equal how many codes you have in the active codes area.
807E9d63 -number of active codes

807E9d64 -beginning of active codes, in straight 32-bit format with value right after.

You can freely edit these codes in memory editor to change them, and unlike the normal active codes, these are side-by-side, which might mean they're applied in a more efficient way, so could it be less strain on the code handler allowing for more codes than usual?

There is this one thing- if write-once "F0" codes can be applied here, then you could turn them all on via an activator(like a button) by changing that number of active codes variable?

Is anyone here interested in any of this at all?

Did I mention this is a great way to bypass the limit on search results, letting you check any result you want even if there's thousands left?


Top
 Profile  
Reply with quote  
PostPosted: Sun Mar 22, 2009 5:20 pm 
Offline
Krew (Admin)
Krew (Admin)
User avatar

Joined: Sun Oct 01, 2006 9:26 pm
Posts: 3765
Title: All in a day's work.
"F0/F1" codes are processed before the in-game code list is built.

I don't have my notes on how it all works, but basically I dumped the memory from the GS Pro main menu in an emulator and disassembled interesting parts of that. There is a hard limit of ~100 lines when the GS does not have an expansion pak. The same limit exists when the expansion pak is available, as well, but could be patched (as a ROM update, would be easiest).

And the 50/51 code types count against the total available lines of code, since they are expanded into normal RAM writes for the in-game code list, which I always thought was bogus.

_________________
I have to return some video tapes.

Feed me a stray cat.


Top
 Profile  
Reply with quote  
PostPosted: Sun Mar 22, 2009 8:36 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
I've gotten around 200 lines of code to work, with 12 multi-line codes + a 170-line 8-bit serial involved.
So, basically you're saying about 100 16-bit codes is the limit? Because I'm sure you can have more if they're mostly 8-bit.

I've come to theorize it's the GS button being active that makes some games freeze randomly, and not the code generator itself, because using GS button activators without the generator on also causes random freezes in games that never freeze without the code generator running.

If you could disable the GS button when the code generator's on, and just use a button activator instead to enter the generator menu, some games would be a lot more hackable with the gameshark.

F0 codes seem to limit the amount of codes you can use, even though it seems like it shouldn't.
I read it's a good way to use large ASM codes and still use a lot of normal codes, but I don't know how to make ASM hacks beyond the fact I don't have the physical equipment required unless I use an emulator.

I think an ASM hack with an expansion pak could allow more codes to be used at once, and perhaps you could even apply the codes more efficiently than they are, since it's been mentioned in some faq there's something wrong with the way they're applied.


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 23, 2009 5:21 pm 
Offline
Krew (Admin)
Krew (Admin)
User avatar

Joined: Sun Oct 01, 2006 9:26 pm
Posts: 3765
Title: All in a day's work.
Each line of code that is enabled before starting the game is "converted" into a ~4-line assembler routine. The assembler is just patched to the end of the "code engine" and then the next line is also converted. At the end of the active code list, a simple jump instruction is pushed, and that's about it. That jump directly calls an interrupt handler. (Essentially, the original interrupt handler is replaced with this primitive code engine. Then the original interrupt handler is run.)

The more 8-bit writes you use, the less space will be available in the code engine, since all constant-writes require 4 instructions, regardless of the data size being written. Even the "serial repeater" codes are expanded into several lines and each is converted to it's own 4-instruction piece of the code engine.

"Highly inefficient" is one accurate way to describe it.

_________________
I have to return some video tapes.

Feed me a stray cat.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 23, 2009 8:18 pm 
Offline
Komrade
Komrade

Joined: Tue Mar 27, 2007 10:18 am
Posts: 1328
It converts the codes into assembly instead of using some of the RAM space for holding an interpreter routine that could read 6 bytes at a time and simulate the code appropriately?

Then is it possible to write a routine like that to make it more efficient? Seems like it'd be much more efficient that way if if the codes aren't interpreted already.

Or is that what you meant when you mentioned patching the ROM?

_________________
Image


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 24, 2009 7:28 am 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
Yes, I believe he is implying that. Now go and make an ASM code so I can use all the Body Harvest weapon pointer data mods I want now. (wanna see my black photon of max-damage death?)
err, though having max damage, it usually enhances the enemy's HP via a glitch, rather than damage it. The next hits, however, will randomly kill them. I really should set the stupid thing to a lower damage so it stops that.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 24, 2009 9:25 pm 
Offline
Komrade
Komrade
User avatar

Joined: Tue Mar 27, 2007 6:23 pm
Posts: 1354
Location: Mario Raceway, 1509.831, 217.198, -564.429
Title: Mario Kart 64 Hacker
Nje789 wrote:
I've come to theorize it's the GS button being active that makes some games freeze randomly, and not the code generator itself, because using GS button activators without the generator on also causes random freezes in games that never freeze without the code generator running.
That's because the Gameshark hardware is such shit that touching it tends to freeze it. Also I find the N64 cartridge slot gets loose after a few years, making the problem even worse.

It'd be neat to hack a better firmware into it, but does anyone still use them?

_________________
Image 143
HyperNova Software is now live (but may take a few tries to load) currently down; check out my PSP/DS/Game Boy/Windows/Linux homebrew, ROM hacks, and Gameshark codes!


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 24, 2009 10:24 pm 
Offline
Krew (Admin)
Krew (Admin)
User avatar

Joined: Sun Oct 01, 2006 9:26 pm
Posts: 3765
Title: All in a day's work.
I don't know, but the only way to make a universal debugger for N64 hardware is by putting it on a GameShark Pro.

_________________
I have to return some video tapes.

Feed me a stray cat.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 25, 2009 6:33 am 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
It's not just the looseness of the slot or pushing the GS button that does it. For instance, my gameshark's been physically modified(I put some electric tape on it to make it better match the sunken port on my N64), and it's so tightly secure it doesn't ever freeze when I push the GS button, but it still randomly freezes when I've never pushed the GS button when 88 code types are used, just like it will with the code generator on

Also- these freezes never occur with games like Quest 64. I freely leave the code generator on with that game in case I want to edit the memory or do a search for some reason while playing.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 25, 2009 5:12 pm 
Offline
Krew (Admin)
Krew (Admin)
User avatar

Joined: Sun Oct 01, 2006 9:26 pm
Posts: 3765
Title: All in a day's work.
Long ago, IceMario attributed the random crashing to "hooking the wrong interrupt vector" ... (Especially with Banjo-Tooie, Perfect Dark, probably Ocarina of Time, etc.) Which probably mostly means the code engine is just non-thread-safe. It could also be that using a different interrupt vector is just "more stable" due to getting executed less often or something. Unfortunately, he never did explain the details. Perhaps disassembling his "Perfect Trainer" GS Pro hack will give some clues.

_________________
I have to return some video tapes.

Feed me a stray cat.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 25, 2009 5:29 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
For Ocarina, the game freezes with just normal codes in use, let alone having the code generator on. But using a disable expansion pak code, EE000000 0000 I think, will stop most all the freezes for normal code use with that game.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 25, 2009 9:44 pm 
Offline
Komrade
Komrade
User avatar

Joined: Tue Mar 27, 2007 6:23 pm
Posts: 1354
Location: Mario Raceway, 1509.831, 217.198, -564.429
Title: Mario Kart 64 Hacker
The code engine is definitely not thread-safe, but it's only a few dynamically generated instructions, running in an interrupt handler. I doubt even another interrupt would likely interrupt it, let alone a thread switch. I would think the interrupt vectors would be above the threading system, and would be where context switching takes place.

In at least some cases, it seems to have to do with the amount of available memory. Para once explained that the code F0000319 00?? would change the amount of memory the game sees available to it, where 40=4MB and 80=8MB, and 78=just under 8MB - enough for nearly all 8MB games to run while leaving a bit of space for the code engine. I found that just using that code with OoT (instead of EE000000 0000) solves all the freezing issues, whether you have the Code Generator active or not. Before that, the rule was always to either use EE000000 0000 or enable the generator. I also seem to remember reading that the EE code type actually does exactly the same thing as that code, just setting the available memory to 4MB.

It's as if the crashing is related to the amount of available memory. Likely the standard libraries used by later games probe for and/or clear out as much memory as they can find, even if the game only uses 4MB (which would explain why OoT is affected even though it doesn't use the Expansion Pak). I can't imagine just what is being done differently though. There are also apparently some glitches/hacks for OoT that only work with the Expansion Pak present (otherwise it just crashes); that could just be because they're causing out-of-bounds array accesses that fall within the upper 4MB, that causes an exception if it's not there.

I haven't looked at OoT's code, but I suspect that the SDK provides the usual malloc/free, and will use as much memory as is available (probing to see how much there is and storing that amount at 80000318), while the game developers decided (likely for speed and to avoid fragmentation) to use a different allocator which assumes the game has 4MB. So normally the game will never touch the upper 4MB, though it might destroy its contents at startup (which normally are undefined anyway) in probing to see if it's there. The question then is why the crashes are so random.

I suspect the reason for that is that while the game won't touch that area, the SDK code will store various information there if it's available, and it's never come up in hacking simply because nobody's really played with that code. So in certain circumstances some important data gets stored there only to be overwritten by the code handler. In fact it could even be that the game does store things there if it's available, and just nobody's noticed because it's not very interesting data. The games are designed to have full control of the hardware and run alone, so even though the game is designed not to use more than 4MB at a time, that doesn't mean it will only ever use the first 4MB of RAM; just that it will never be using more than 4MB of the total amount at once.

Mario Kart uses a similar allocation system, so I wouldn't be surprised if OoT does as well. The game simply has a large static buffer, big enough to hold all the textures, vertices, etc of the most complex track, and has a pointer to the end of the buffer. When it copies data from ROM it copies it into that buffer and moves the pointer back to the beginning of the data. For a game like this where everything will be deallocated before loading the next level, it has several advantages. No fragmentation and no time required to deallocate. You just reset the pointer to the end of the buffer and overwrite whatever was there before, because it's no longer needed. In this case the amount of RAM actually available to the game is irrelevant, as it will just use this static buffer which is a fixed size. It also makes it trivial to measure the amount of free memory; just compare the pointer to the beginning address of the buffer. (Though Mario Kart doesn't bother with this and will just write over code if it runs out of memory; normally, that should never happen, so there's no point checking for it.)
(A bonus of this method for us is that all you have to do is find the code that sets the initial pointer, and change it to 80800000. Bam. The game now uses all of the upper 4MB for its resources, and you still have the old buffer to put whatever you want in, that should never be overwritten. If you knew how to detect the Expansion Pak it'd be trivial as well to do this only when it's available. :D)
OoT, then, may well do similar with multiple buffers, and set one of them to the very end of the available memory space. So when it sees 8MB available it sets that to the very end of available RAM, and when the buffer gets full enough it ends up overwriting the code handler that's stored right near the end of RAM.


As for only freezing when GS Button codes are active, the most likely reason is the code handler simply being longer, due to the added check for the button in each code. Another possibility is caching weirdness, or ROM access conflict - the code must probe some address on the cartridge bus to test the button, and that could potentially conflict with the game trying to read something from ROM. That would especially explain why you hear blips and pops in the music when using the generator, more often in unstable areas, as the game is constantly streaming music from ROM.

_________________
Image 143
HyperNova Software is now live (but may take a few tries to load) currently down; check out my PSP/DS/Game Boy/Windows/Linux homebrew, ROM hacks, and Gameshark codes!


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 26, 2009 7:25 am 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
Wouldn't it be better to just A-never use GS button codes, and B- turn the code generator on by a button on the controller and disable the GS button when using the code generator?

Actually, a controller-activated code generator menu instead of the GS button sounds VERY nice.

I'm sure there'd be a way. If you look in the code generator's memory area, you can even see it detecting your button presses by changing values in real-time in memory editor if you're looking at them, and this would be a perfect activator code for what pressing the GS button triggers that brings the code generator menu up.

Then, just disable the GS button check, whatever the difference there is when you have a gs button code on, or when it's off(although, you'd have to have a different offset for this since it'd load in a different place when the code generator's on).


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 26, 2009 5:24 pm 
Offline
Krew (Admin)
Krew (Admin)
User avatar

Joined: Sun Oct 01, 2006 9:26 pm
Posts: 3765
Title: All in a day's work.
Disabling the GS button checks is probably trivial. However, keep in mind that using the parallel port also requires accessing the cartridge bus. So if cart bus conflicts are the problem, then the proper solution would be wrapping any GS button/LPT accesses inside a cart DMA wait loop. To find all instances of cart bus accesses in the GS Pro code generator, you should dump memory 0x80400000 - 0x80800000, and search for LUI instructions with the value 0xBE40 -- address 0xBE400000 is read/written by the code engine and code generator to check the GS button. The LPT is either the same address or a series of addresses in this range.

Then you just create a test code that patches those piece of code to skip over those address accesses. If you never crash and the blips and bleeps go away, there's your answer. (The whole code generator will essentially be disabled if you did the test code properly ... because you're disabling the human interface to it altogether). That will at least give you an idea if doing the DMA wait loop will help at all.


To cover some more information that HyperHacker noted, the problem with memory management is one that has raged since the invention of the cheat device. The code he mentions is part of the SDK's internal memory manager, which is used to give developers some sense of how much memory is available for them to use. But this is just a hint, and any game can (and some do) ignore it.

The problem with memory management is that the code engine needs to share memory with the game. And neither knows what the other is doing, at any point in time. By limiting the game to use only so-much memory (with the given code, for example) you are allowing for a small reserve that the code handler should be able to use without conflicting with what the game wants to use.

With a full 8MB of memory, the game will allocate heap (arena) space right around the same area that GS wants its code engine. That's why memory-management related crashes seem so random. The game won't crash until it has allocated enough memory to overflow into the GS code engine. Doing that reliably (to debug the problem, maybe) can be tricky.

With only "4MB" of memory reported to the SDK, some games have logic issues that make it seem like they just ignore the setting. For example, I've seen some which check if the memory size is LESS THAN or GREATER THAN some arbitrarily chosen number. Rather than checking if it is exactly equal to 0x00400000 or 0x00800000 (which I imagine would be more fitting of the N64 hardware). This kind of error can cause all kinds of fun problems, but they could be fixed by analyzing the code which reads that memory size variable.

FWIW, GCNrd uses the same exact trick to allocate its own memory. And yes, there are still games that ignore it and do whatever they want, potentially trashing the debugger, or trashing parts of itself, depending on how things are relocated when simulating less available memory.


About the interrupt/threading/race condition issue: Once an interrupt handler begins, further interrupts are disabled until a few actions are taken to re-enable them: 1) the interrupt must be acknowledged. This is done by resetting the interrupt state at the interrupt controller register(s). 2) if interrupts are explicitly disabled during the interrupt handler prologue (as they should) then the interrupt handler epilogue must also explicitly re-enable interrupts.

There are some exceptions to this rule, however! Interrupt priorities can further interrupt any interrupt handler with a lower priority. For example, the reset interrupt is generally given the highest priority of any interrupt. This is so the machine can be reset, even while handling a more common, general interrupt. And Then there are also exceptions, and exception priorities. All exceptions take priority over interrupts. But exceptions are usually caused by program errors, rather than outside hardware wanting to get the CPU's attention (as in the case of interrupts). Some examples are accessing invalid memory, executing invalid instructions, dividing by zero, etc.

That said, I'm wondering if the code handler should explicitly disable/enable interrupts...

_________________
I have to return some video tapes.

Feed me a stray cat.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 27, 2009 5:13 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 30, 2007 9:53 am
Posts: 43
I could find that value in that area by going that area, then doing a text search with that value by editing the search value for the text editor in the memory editor. It'll find every instance of it if you keep searching for it with the text search, even most non-text values.

Thing is, I wouldn't know what to do with it if I found it. I can't connect my gameshark to a PC, so I have no way to interpret what's going on.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 26, 2009 1:30 am 
Offline
Komrade
Komrade
User avatar

Joined: Tue Mar 27, 2007 6:23 pm
Posts: 1354
Location: Mario Raceway, 1509.831, 217.198, -564.429
Title: Mario Kart 64 Hacker
807E9B34 was it, that the text is stored at? Something like that. I'm pretty sure GSCC can dump all 8MB anyway though. Abusing the text search for that isn't the best method anyway, since it locks right up if any byte is < 0x20, and does case-insensitive searching.

How do games detect the amount of memory available anyway? I'd like to hack Mario Kart to be able to use it without assuming it's always there.

I wonder too if you'd get more stability just by moving all the code handler to somewhere in the 80400000-80600000 range. A lot of games allocate from the end of the heap, so as long as you put your code handler at the very beginning, it's much less likely to get overwritten.

Or hell, patch the memory allocator to never consider that area free. :p

_________________
Image 143
HyperNova Software is now live (but may take a few tries to load) currently down; check out my PSP/DS/Game Boy/Windows/Linux homebrew, ROM hacks, and Gameshark codes!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group