Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2014-03-18 00:47:27

abhmul
Member
Registered: 2013-03-30
Post 5/12

Adding a new Trainer Class

I was wondering how to properly add a new trainer class to Pokemon Silver and had a few questions.

-Would this require some work with ASM?
-Could I just do this with some scripting, hex editing, and sprite inserting?

For example I wanted to split the Team Rocket Executive Class into various classes specific to each Executive.

I would grateful for any help given.

Offline

#2 2014-03-18 06:39:20

Miksy91
Member
Registered: 2010-10-16
Post 2,077/2,317

Re: Adding a new Trainer Class

You would have to work with a few tables and either repoint them elsewhere, or through some other method, make room for a new 2- (or 3-) byte entry to the table.

Offline

#3 2014-03-18 20:28:57

abhmul
Member
Registered: 2013-03-30
Post 6/12

Re: Adding a new Trainer Class

What are the offsets for where that data is stored?

Offline

#4 2014-03-18 20:36:39

Miksy91
Member
Registered: 2010-10-16
Post 2,078/2,317

Re: Adding a new Trainer Class

abhmul wrote:

What are the offsets for where that data is stored?

Welcome to rom hacking!

That is something you need to find out on your own :)

Offline

#5 2014-03-19 03:09:45

abhmul
Member
Registered: 2013-03-30
Post 7/12

Re: Adding a new Trainer Class

So I located the offset for where the number of trainer classes is located and raised that number by one. Then I figured I probably need to add a sprite for this new trainer class the game thinks it has so I figured I might be able to do that by adding an extra pointer the to the pointer table for trainer sprites, but there was no free space right after the pointer table which meant I needed to move the pointer table. In order to that I need to find the pointer to the pointer table.

So I went on a voyage to find this pointer which had to be 20 00 40 since my offset for the pointer table is x80000. I did a search for all strings equivalent to 20 00 40 in the ROM with Goldfinger and eliminated any that looked like they were part of some tileset in Tile Layer Pro. I ended up with 7 possible offsets for the pointer to the trainer sprite pointer table. Now here is where I ran into my problem. I assumed that if I went to the correct offset and replaced the 20 00 40 with some random hex values the trainer sprite would get all screwy when I battled someone. I tested all 7 possible offsets, but to no avail... Each one I changed seemed to have no affect whatsoever on the entire game.

Is there somewhere I screwed up? And is there an easier method to finding this elusive pointer?

Last edited by abhmul (2014-03-19 03:11:30)

Offline

#6 2014-03-19 06:57:29

Miksy91
Member
Registered: 2010-10-16
Post 2,079/2,317

Re: Adding a new Trainer Class

Yep, there was a problem with the method you were using.
If you think about it, why should we have a "3-byte pointer" to the trainers' pictures pointer table? The thing is, we don't.

Everytime we use a pointer table of some sort, we of course need to somehow access that table with a "pointer" or some sort. This pointer is often part of a load instruction, most likely "ld hl, $table". This is because of the fact that the table has entries in it; most tables consist of entries that are two bytes long, and so, the whole routine behind their handling can be located in the same rom bank.

In this situation you're looking for, the routine behind handling that table (at 0x80000) is elsewhere in some other rom bank. Gameboy CPU works so that we can access only two rom banks at the same time; rom bank 0 and a variable rom bank. So when we're looking at this table at 0x80000, we must have the code in rom bank 0 - I can't think of any other option at least.

As an example, we probably have a routine such as this located somewhere in the rom file;

ld d, 20 (rom bank)
hl hl, 4000 (address of table)
ld a, [trainer class address in ram]
ld b, 00
ld c, a
add hl, bc
add hl, bc
add hl, bc

// now hl has the address of 0x4000 + 3 * [trainer class number]

// Now what we do is call some routine from rom bank 0 that does what we're looking for. After that is done, we return here and keep doing something else.

call $routineFromBank0


@routineFromBank0
ld a, [FF9F]   // get current variable rom bank
ld e, a        // store that to reg e

ld a, d        // get rom bank 20 to a
rst 10         // change variable rom bank to 20
               // now we can access data from rom bank 20 and hl has the address of the data what we're looking for!


ldi a, [hl]
ld b, a        // store rom bank value of the trainer sprite pointer to b

ldi a, [hl]
ld h, [hl]
ld l, a        // these following three instructions pick up a (little-endian) pointer value located in address hl and store that in hl
               // now b:hl has the address of where the trainer sprite is located

ld a, e         // get the "original" rom bank to register a
rst 10         // change the rom bank back to what it was
ret

Last edited by Miksy91 (2014-03-19 07:00:09)

Offline

#7 2014-03-20 02:50:00

abhmul
Member
Registered: 2013-03-30
Post 9/12

Re: Adding a new Trainer Class

My understanding of ASM is very weak (though I'm learning) and I probably screwed up somewhere again. I searched for the instruction

ld d,$20

but couldn't find anything remotely similar in Bank 0 to what you posted. Then I tried the same function with all the other registers in the place of "d" and still got nothing. Are there other possibilities as  to what this code could look like?

Also (just side question) are all the pointers to various pointer tables located in Bank 0?

Last edited by abhmul (2014-03-20 02:55:07)

Offline

#8 2014-03-20 06:38:46

Miksy91
Member
Registered: 2010-10-16
Post 2,080/2,317

Re: Adding a new Trainer Class

That code of mine was just an example of what the code could look like. You can't find it like this.
What you should do would be debugging with bgb, or checking out pokecrystal disassembly if you can find the corresponding routine in that and then look it up in your Silver rom file.

abhmul wrote:

Also (just side question) are all the pointers to various pointer tables located in Bank 0?

Well everytime we have to access a table that is in a different rom bank than we are at the moment, we'll have to move there from rom bank 0 first.
Calling a routine from another rom bank is easy;

ld a, rom bank
ld hl, pointer/address
rst 8 ' call 0008 instruction and the code for the bank switch (+ returning here afterwards) starts there at 00:0008

Now in this case we don't call any routine from another variable rom bank though.
Nevertheless, we still have to move to rom bank 0, change the variable rom bank and pick up some values from that table that is in that another rom bank. Then we can return back to the rom bank we came from.

Anyway... you could try debugging and seeing if you can find the code using that table. If I was you, I would start off by opening the rom with bgb, setting a breakpoint to 20:4000, or 20:40XX (in which XX is [trainer class number] * 3), and seeing if you can find the code that uses the table then. You would of course have to enter a trainer battle before this table is accessed first.
Another good way of tracking it down would be setting a breakpoint to address of "trainer class number". I think that is something like D118 or D11B. You can find the right address in Scripting Compendium if you don't know it.

Last edited by Miksy91 (2014-03-20 06:44:36)

Offline

Board footer

Powered by FluxBB