Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#126 2012-12-02 13:35:49

Sawakita
Administrator
Registered: 2010-10-16
Post 352/364

Re: Pokemon Red: Palettes

@Danny-E 33:
I didn't found practical notes. Anyway, to use dynamic SGB packets instead of hardcoding each one by itself, you could write a routine that loads a "base" PAL_SET packet (which you can accomplish by copying the existing packet located at 0x72428) into RAM:CF1D. You can use routine 0x9D to copy data from a different bank into RAM. Here's the source code from pokered, if you want to see what it does:

FarCopyData: ; 009D
; copy bc bytes of data from a:hl to de
    ld [$CEE9],a ; save future bank # for later
    ld a,[$FFB8] ; get current bank #
    push af
    ld a,[$CEE9] ; get future bank #, switch
    ld [$FFB8],a
    ld [$2000],a
    call CopyData
    pop af       ; okay, done, time to switch back
    ld [$FFB8],a
    ld [$2000],a
    ret

Notice that you have to specify the bank, source pointer, destination pointer and the number of bytes to copy (in your case it would be 0x10 bytes). Your new routine would then overwrite the byte at 0xCF1E with a parametric palette ID, and then call the routine that sends SGB packets.

This way you could call the new routine passing the palette ID as a parameter, each time you want to change the palette. Something like:

ld a,SOME_PALETTE_ID
call SendDynamicallyBuiltPalettePacket

--

Miksy91 wrote:

the code isn't that large though

I never said it was.

Miksy91 wrote:

Of course if the space in rom bank 0 is so limited that there is no point in adding such code, no particular reason in creating one either.

Well, taking advantage of the RST vectors would neither affect nor be affected by the free space in bank 0; vectors have their 8 bytes reserved in the beginning of the ROM anyway, so you would just implement them as shortcuts to some existing often-used routines (Bankswitch and Predef come to mind), and be done (of course doing this would make sense only if you had the complete source code of the game, not the assembled/linked result).

stag019 wrote:

Which makes me wonder though. How much space does it save? How many calls are there to this function in Generation I? I'd like to know how much it would have benefitted to have used the RST vectors in Generation I, since it's been said that space was an issue during development.

Doing a quick search with a hex editor I found:

  • 201 instances of CD D6 35call Bankswitch»), which means using rst shortcuts would have saved 402 bytes;

  • 59 instances of C3 D6 35jp Bankswitch»), which means using rst shortcuts would have saved 59 bytes;

  • 314 instances of CD 6D 3Ecall Predef»), which means using rst shortcuts would have saved 628 bytes;

  • 52 instances of CD 6D 3Ejp Predef»), which means using rst shortcuts would have saved 52 bytes;

  • 149 instances of CD B5 00call CopyData»), which means using rst shortcuts would have saved 298 bytes;

  • 25 instances of C3 B5 00jp CopyData»), which means using rst shortcuts would have saved 25 bytes;

The total would then be 1464 bytes, just with three routines.

This survey didn't considered that some of the matches are probably just random data and not actual code, but even reducing the number of matches, you would still have more than 1KB of saved space (in a very cheap and quick way, which is relevant). On a 512KB cartridge (that is the size of original Red/Green japanese ROMs, if I'm not wrong) is not bad. Probably better than putting together a messy and hacky engine just to get everything fit in.

Last edited by Sawakita (2012-12-02 13:39:11)

Offline

#127 2012-12-24 02:25:00

Danny-E 33
Administrator
Registered: 2012-06-09
Post 302/1,045

Re: Pokemon Red: Palettes

Okay, sorry it's been too long, I've gotten pretty busy with school and finals lately. I had to review everything we discussed and then I gave this a shot. Here's what I got so far.

Starting in the middle of the Oak script...

; 01:614C
ld a, $86  ; the palette id for Oak (just for my hack, of course)
call $7C59 ; goto GotPaletteID
nop        ; *for these nops, I scooted a chunk of the
nop        ; Oak script from $6154-$616B to $6151-$6168
nop        ; so that the nops were then at $6169.

; 01:6169
call $7C49 ; goto GetNidoPalID

; 01:6189
call $7C4D ; goto GetHiroPalID

; 01:61A4
call $7C54 ; goto GetRivalPalID

; 01:61BF
call $7C4D ; goto GetHiroPalID

; 01:698B
call $7C4D ; goto GetHiroPalID

; 01:69D3
call $7C54 ; goto GetRivalPalID

; GetNidoPalID: 01:7C49
ld a, $3D ; Nidorino's palette id
jr $0C    ; goto GotPaletteID

; GetHiroPalID: 01:7C4D
call $190F
ld a, $84  ; Hiro's palette id
jr $05     ; goto GotPaletteID

; GetRivalPalID: 01:7C54
call $190F
ld a, $85  ; Rival's palette id

; GotPaletteID: 01:7C59
push af      ; preserve palette id
ld hl, $670B ; pointer for after bank switch
ld b, $1C    ; bank to switch to
jump $35D6   ; Bankswitch, then the code continues at 1C:670B

; 1C:670B
ld bc, $0010 ; Copy bc bytes
ld de, $CF2D ; to de
ld hl, $6428 ; from hl.
call $00B5   ; call CopyData
pop bc       ; Retrieve
pop de       ; palette id
pop af       ; from the stack.
push de      ; Restore pointers
push bc      ; to the stack.
ld hl, $CF2E ; Load palette id into packet and
ldd [hl], a  ; decrement hl to the beginning of the packet.
jp $5FEB     ; SendSGBPacket

After sending each packet at $5FEB, it returns to the end of the bankswitch routine to return the bank to ROM 01 and continues the Oak script.

This works very successfully. Do you have any advice for optimization?
As far as optimization, can you think of a way to eliminate all the push/pops to retrieve the id from the stack?
Also, you've said that the packets in RAM start at $CF1D, and you've also said $CF2D. After taking a deeper look at it, I believe you mean $CF2D, right?
And just a note, at $614C, I overwrote the 8 wasted bytes that are the bit check to skip the Oak intro in order to get a bit extra space.

Last edited by Danny-E 33 (2012-12-26 11:27:43)


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

#128 2012-12-28 18:36:50

Danny-E 33
Administrator
Registered: 2012-06-09
Post 308/1,045

Re: Pokemon Red: Palettes

Sorry if I took too long to reply. Are you still around? :P


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

#129 2013-01-07 20:45:19

Sawakita
Administrator
Registered: 2010-10-16
Post 356/364

Re: Pokemon Red: Palettes

Hi, sorry, I somehow failed to reply before :P

Good stuff, so far.

Danny-E 33 wrote:

After sending each packet at $5FEB, it returns to the end of the bankswitch routine to return the bank to ROM 01 and continues the Oak script.

This works very successfully. Do you have any advice for optimization?
As far as optimization, can you think of a way to eliminate all the push/pops to retrieve the id from the stack?

An alternative that comes to mind is storing/retrieveing a's value into/from RAM (for example 0xCF91 and 0xD11E seem to be two general purpose temporary storage RAM locations) instead of pushing/popping, maybe. It wouldn't save you any space in the total computation of bytes used, though, because you would use 2 more bytes in the calling code (bank 1) and 2 less bytes in the called routine (bank 1C).

Danny-E 33 wrote:

Also, you've said that the packets in RAM start at $CF1D, and you've also said $CF2D. After taking a deeper look at it, I believe you mean $CF2D, right?

I should re-check my notes but IIRC there are two "buffer", so you can store two dynamic packets at the same time. I'll see and add on to this later, if I find something.

Offline

#130 2013-01-08 04:16:28

Danny-E 33
Administrator
Registered: 2012-06-09
Post 329/1,045

Re: Pokemon Red: Palettes

Sawakita wrote:

Hi, sorry, I somehow failed to reply before :P

Good stuff, so far.

No worries. :)
And thanks! You know I couldn't have accomplished such a web of code without you as my teacher! :)

Sawakita wrote:
Danny-E 33 wrote:

After sending each packet at $5FEB, it returns to the end of the bankswitch routine to return the bank to ROM 01 and continues the Oak script.

This works very successfully. Do you have any advice for optimization?
As far as optimization, can you think of a way to eliminate all the push/pops to retrieve the id from the stack?

An alternative that comes to mind is storing/retrieveing a's value into/from RAM (for example 0xCF91 and 0xD11E seem to be two general purpose temporary storage RAM locations) instead of pushing/popping, maybe. It wouldn't save you any space in the total computation of bytes used, though, because you would use 2 more bytes in the calling code (bank 1) and 2 less bytes in the called routine (bank 1C).

Yeah, I didn't think about that. I think I'll just leave it the way it is. I haven't noticed any problems so far from disturbing the stack. Do you have a preference?

Sawakita wrote:
Danny-E 33 wrote:

Also, you've said that the packets in RAM start at $CF1D, and you've also said $CF2D. After taking a deeper look at it, I believe you mean $CF2D, right?

I should re-check my notes but IIRC there are two "buffer", so you can store two dynamic packets at the same time. I'll see and add on to this later, if I find something.

Sounds good.

Also, I still haven't successfully replaced the palette for the Pokedex screen with the red health bar palette.
I tried finding the call it uses to $5FEB but I've learned that the code it is reading when it executes that call is code that is read in multiple instances to send a palette $10 packet. So adding in some code or modifying the packet it sends doesn't work because it affects the packet everytime that code is read.
I've learned from editing the Oak intro script that it is near immpossible to make the code skip the palette changes entirely. So for example, the Oak intro still sends palette $10 packets throughout (such as when the New Name screen comes up), but then a custom packet is always sent before sprites are displayed on the screen.
I plan on doing a similar thing here. Let it send a palette $10 packet and then add in code to send a custom packet.
So now it's a matter of finding a specific ASM script responsible for putting together the Pokedex screen.
Well, finding a call to $5FEB already failed... I tried a call to $1922, but then I realized there are no text boxes on the Pokedex screen...
Are there other big (probably Bank 00) routines that are called to generate things on the screen such as text that I should try a breakpoint at and then trace back in the stack to find where it was called from in order to find the Pokedex screen's ASM script?
I fear my knowledge of big, game-engine routines is too small to think of where to put a break point in order to find the Pokedex screen's script.


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

#131 2013-01-08 04:29:43

stag019
Idea Killer
Registered: 2011-01-05
Post 266/630

Re: Pokemon Red: Palettes

Go into the disassembly and read DisplayPokedexMenu_, which is located at 10:4000. See if that helps.


You can try to hide yourself in this world of pretend; when the paper's crumpled up, it can't be perfect again.

Offline

#132 2013-01-08 05:28:11

Danny-E 33
Administrator
Registered: 2012-06-09
Post 331/1,045

Re: Pokemon Red: Palettes

After lookin' at the disassembly, here's what I tried out:

;10:401D
ld b, $1C    ; bank to switch to
call $67F3   ; free space

;10:67F3
ld hl, $66ED ; pointer after bank switch
jp $35D6     ; Bankswitch

;1C:66ED
ld hl, $66F3 ; pointer to packet
jp $5FEB     ; SendSGBPacket

Seems to work great!
And there are no unwanted side-effects, that's always a plus.

Thanks for helpin' me out, stag! I really appreciate it!

Last edited by Danny-E 33 (2013-01-08 05:33:16)


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

#133 2013-01-09 17:37:42

Sawakita
Administrator
Registered: 2010-10-16
Post 357/364

Re: Pokemon Red: Palettes

Nice. So, did you manage to avoid re-sending palettes after the original ones?

Offline

#134 2013-01-10 03:54:07

Danny-E 33
Administrator
Registered: 2012-06-09
Post 340/1,045

Re: Pokemon Red: Palettes

Actually, yes! I didn't thing that was gonna be possible (it is definitely near impossible for the Oak script like when the player types in a new name), but with the address stag019 provided, it actually cut around sending a useless packet because I got rid of the code that called $3DEF with a certain parameter in b. I think it was $08.


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

Board footer

Powered by FluxBB