Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#51 2012-09-12 02:46:44

Danny-E 33
Administrator
Registered: 2012-06-09
Post 117/1,023

Re: Pokemon Red: Palettes

Here's a GSC sprite that looks great in my Red hack now! :D

Kk0bN2r.png

Sorry it took me a couple days to upload this. I had a lotta personal organizing I had to do.

Thanks alot for helping make this idea a reality, I couldn't have done it without you :)

EDIT: Replaced the screenshot with the awesome player backsprite (credit for the sprite goes to Poketto) now that my hack supports 6x6 backsprites thanks to Sawakita and the new Pokeballs' palette discussed further down :)

Last edited by Danny-E 33 (2013-06-08 11:45:43)


Red Hack: Pokémon Prototype

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

Offline

#52 2012-09-22 01:29:21

Danny-E 33
Administrator
Registered: 2012-06-09
Post 135/1,023

Re: Pokemon Red: Palettes

So I wanted to look into changing the default palette used when you first enter a battle and it shows the number of Pokemon you have as the little Pokeballs and it shows which ones are psn, fainted etc. Then moments later, it is replaced with your active Pokemon's health bar and the palette it is using is re-evaluated based on your current amount of health.

By default, the Pokeballs' palette is the green health bar palette, palette id 1F. I want to simply change this to the red health bar palette, id 21. I went on a little scavenger hunt and the default palette's id for the player's side is stored in the byte at 0x71E2D.

I changed this byte to 21 hoping the Pokeballs would show up red and my Pokemon's health bar palette would be re-evaluated and would still be green. Apparently, that byte determines the starting point of the 3 health bar palettes. So my Charizard came out with full health and had a red health bar. When I had half health, it was using the blue badge palette. And when I had low health, it was using the cave palette.

I have a feeling it works something like this:

Get the starting palette id 1F for the 3 health palettes from 0x71E2D.
Use that palette id until a Pokemon is sent out.
If the Pokemon's health is good, use id 1F+00.
If the Pokemon's health is fair, use id 1F+01.
If the Pokemon's health is bad, use id 1F+02.

Do you think there is any way I can make it say:
Use id 1F+02 until a Pokemon is sent out.
But keep the rest of it the same?

Of course, I couldn't observe any of this code in action cause I couln't get any sort of breakpoint to cooperate in this process. Stupid breakpoints...

Last edited by Danny-E 33 (2012-10-12 03:01:06)


Red Hack: Pokémon Prototype

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

Offline

#53 2012-10-03 15:55:35

Danny-E 33
Administrator
Registered: 2012-06-09
Post 140/1,023

Re: Pokemon Red: Palettes

So I guess I'll start by asking, why do you think I can't get any sort of access, read, write, execute breakpoint to work with 0x71E2D or the byte before that which might be the opcode used with the byte at 0x71E2D?


Red Hack: Pokémon Prototype

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

Offline

#54 2012-10-03 17:58:08

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

Re: Pokemon Red: Palettes

I'm sorry, I would have replied to your previous post, I just missed it.

Danny-E 33 wrote:

So I guess I'll start by asking, why do you think I can't get any sort of access, read, write, execute breakpoint to work with 0x71E2D or the byte before that which might be the opcode used with the byte at 0x71E2D?

The opcode itself begins, as you correctly noticed, at address 0x71E2C: for "code" breakpoints you shouldn't use access breakpoints, but instead you should use normal breakpoints (the ones that make the "breakpointed" line red).


As for the previous question itself: you don't have to modify this code. I came up with a hacky (as in "unclean, but very practical") workaround. There's a routine that supposedly initializes RAM locations involved in battles: this init function is at 14:65af. 04:7a8f (an additional information, not required for solving your question, is that that function is called by routine at 3e5c, I'm just putting it here for future reference, when I'll forget about it...). It zeroes several RAM locations including 0xCF1D and 0xCF1E: these RAM locations are used to determine the SGB color to use in the screen areas where pokeballs (and, later, health bars) are.
We can take advantage of this indiscriminate usage of these RAM locations. We know that when [RAM:CF1D] = 0 our pokeball area (or, later, our health bar are) is coloured with green palette (the same applies for RAM:CF1E and enemy pokeball/healthbar area).

If instead of letting the init routine load 0x00 into RAM:CF1D and RAM:CF1E we create a little branch where we load a value of 0x02 into these RAM locations, we'll obtain the desired result (i.e. red pokeballs without causing red full healthbars).

I believe you can accomplish the rest of the solution on your own. For any problem, feel free to ask.

Last edited by Sawakita (2012-10-04 09:29:11)

Offline

#55 2012-10-04 06:15:34

Danny-E 33
Administrator
Registered: 2012-06-09
Post 141/1,023

Re: Pokemon Red: Palettes

So I wanted to get a better understanding of what was going on so I added a breadpoint at 1C:5E29 where the code reads:

ld a, [CF1D] ; get 00 from CF1D and put it into a
add a, 1F    ; a becomes 1F
ldi [hl]. a  ; puts 1F into CF2E (player's health bar palette)
inc hl       ; hl becomes CF2F
ld a, [CF1E] ; get 00 from CF1E and put it into a
add a, 1F    ; a becomes 1F
ldi [hl], a  ; puts 1F into CF2F (enemy's health bar palette)
inc hl       ; (continues by reloading the player and enemy sprite palette from b and c)

So I know you said this isn't the code I want to be editing, but while I was here I was just experimenting and by clicking on register pair af in bgb's debugger and changing a's value to 02 each time 1F was right about to be added caused the Pokeballs to be red but a full health bar to be green immediately afterwards.

So this shows that if the bytes at RAM:CF1D and CF1E were 02 when the Pokeballs were being loaded, then they would use the red palette id as long as those two bytes were 00 again whenever a health bar is being loaded so the correct palette can be determined based on the current amount of health.

But I'm not sure how to make it so that those two bytes have 02 in them when the Pokeballs are being loaded but then have 00 in them again when the health bars are being loaded...
And I tried putting a breakpoint at 04:7A8F also but that routine was called so many times it was impossible for me to follow along and know when/how it was being used to zero out CF1D and CF1E...


Red Hack: Pokémon Prototype

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

Offline

#56 2012-10-04 09:27:42

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

Re: Pokemon Red: Palettes

Sorry, I made a mess when posting the addresses: the "battle init" function is at 14:65af (the part you're interested in begins at 14:65d7). Without the routine's address (i.e. in case you'll be given wrong addresses again) you could also find it by putting an "on write" breakpoint to RAM:CF1D.

(I'll fix my previous post too, I don't even know how I wrote such unrelated info)

Offline

#57 2012-10-04 14:18:23

Danny-E 33
Administrator
Registered: 2012-06-09
Post 142/1,023

Re: Pokemon Red: Palettes

Sawakita wrote:

you could also find it by putting an "on write" breakpoint to RAM:CF1D.

That's actually what I did first before I used a regular breakpoint at 1C:5E29 and I kept seeing the address 14:65AF but you never said anything about it so I just ignored it :P I'll take a look at that when I get home tonight.


Red Hack: Pokémon Prototype

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

Offline

#58 2012-10-06 05:24:14

Danny-E 33
Administrator
Registered: 2012-06-09
Post 143/1,023

Re: Pokemon Red: Palettes

Awesome! This really wasn't too difficult :)

Kk0bN2r.png

I changed the code at 14:65D7 to:

call 6A59
ld a, 00

And I changed the code at 14:6A59 to:

ld a, 02
ld hl, CF1D
ldi [hl], a
ld [hl], a
ret

So is this at least pretty close to what you had in mind?

Also, with the previous help from stag019 about supporting a unique player back sprite palette, I've also added a specific palette for Venusaur's back sprite:

2nxzp6C.png

This way, Venusaur's back sprite can have a deep green color for the leaves, whereas that green color would look bizzare with Venusaur's front sprite since the body and the leaves need to share the same color.
What do you think?

Last edited by Danny-E 33 (2013-06-08 11:32:40)


Red Hack: Pokémon Prototype

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

Offline

#59 2012-10-06 11:57:57

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

Re: Pokemon Red: Palettes

Danny-E 33 wrote:

I changed the code at 14:65D7 to:

call 6A59
ld a, 00

And I changed the code at 14:6A59 to:

ld a, 02
ld hl, CF1D
ldi [hl], a
ld [hl], a
ret

So is this at least pretty close to what you had in mind?

Well done. This is almost exactly what I meant. Out of curiosity: why did you put the branched code at 14:6A59, instead of 14:6A42 (i.e. the beginning of the end bank's free space)?

Offline

#60 2012-10-06 16:55:40

RPD490
Member
From: Blackthorn City, Johto
Registered: 2012-09-29
Post 32/259
Website

Re: Pokemon Red: Palettes

Now if only we could make more room in the text to add names to Trainers

Offline

#61 2012-10-06 20:44:51

Danny-E 33
Administrator
Registered: 2012-06-09
Post 148/1,023

Re: Pokemon Red: Palettes

Sawakita wrote:

Well done. This is almost exactly what I meant.

Thanks :) As always, couldn't have done it without you.

Sawakita wrote:

Out of curiosity: why did you put the branched code at 14:6A59, instead of 14:6A42 (i.e. the beginning of the end bank's free space)?

I have no idea... The ROM map only has map header information documented in bank 14 and I haven't repointed any map header information yet.. But I have code in there from 52A43-52A58... Perhaps it was a small edit to part of a routine but I don't have that address written anywhere in my notes... Maybe it was just a mistake :P
That code also doesn't look familiar in the slightest, so it was probably just a fluke...

Last edited by Danny-E 33 (2012-10-06 20:45:51)


Red Hack: Pokémon Prototype

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

Offline

#62 2012-10-07 18:21:41

Danny-E 33
Administrator
Registered: 2012-06-09
Post 155/1,023

Re: Pokemon Red: Palettes

Well got rid of that mysterious code at 0x52A43 and put this new routine at 0x52A42 instead of 0x52A59 like I did originally.
I'm pretty sure that random code won't be missed.
If it was important, I'll probably realize it sooner or later. And if I don't, then it obviously wasn't important enough. :P


Red Hack: Pokémon Prototype

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

Offline

#63 2012-10-14 17:04:26

Danny-E 33
Administrator
Registered: 2012-06-09
Post 172/1,023

Re: Pokemon Red: Palettes

Well, I thought I was done. But unfortunately, I'm not.

The Pokeballs are still green whenever you faint an enemy Pokemon and it shows their party again before they send out their next Pokemon. But I don't think this ever happens again for the player. I don't think there is another case where it shows the player's party.

00:3DF9 is called at 0F:4E91 and this routine is responsible for choosing a palette based the Pokemon's current amount of health.
It seems the amount of health is reduced to some sort of fraction where 0x30 means full health.
When it is showing the enemy's party, register a always equals 0x30 which results in 00 (green health bar palette) being put into d which is then put into hl ($CF1E).

I've done alot of brainstorming, but I don't have any idea how to differentiate when this routine is being used for the enemy party vs when it is being used for the enemy health bar...
So I don't know how to make sure 02 is put into $CF1E when the enemy party is being shown but then either 00, 01, or 02 is appropriately put into $CF1E when the enemy health bar is being shown.


Red Hack: Pokémon Prototype

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

Offline

#64 2012-10-14 18:50:40

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

Re: Pokemon Red: Palettes

I've gave a look at how the pokeball OAMs are loaded, and found out (I didn't explore very accurately, but since the result was good, it seems reliable) that the palette is loaded in a quite "hackish" way: they simulate a full-health pokemon. This is done by using the value 0x30 which, as you correctly figured out, means the health is 100% and then the health-bar must be green (for values > 0x1A the health bar is green, for values between 0x0A and 0x1A the palette is yellow while values < 0x0A cause a red palette). So all I did was changing the 0x30 to 0x00 and the result was seemingly successful (i.e. only the pokeballs are red, while healthbars are rendered correctly).

Here is the code snippet:

BEFORE:
ROMF:4664 21 1e cf         ld   hl,cf1e
ROMF:4667 1e 30            ld   e,30
ROMF:4669 cd 90 4e         call 4e90

AFTER:
ROMF:4664 21 1e cf         ld   hl,cf1e
ROMF:4667 1e 00            ld   e,00
ROMF:4669 cd 90 4e         call 4e90

By the way, to find where this code was I put an access breakpoint at 0x8310, where pokeball graphics are loaded, and back-traced from there.

Last edited by Sawakita (2012-10-14 19:04:32)

Offline

#65 2012-10-14 20:22:52

Danny-E 33
Administrator
Registered: 2012-06-09
Post 174/1,023

Re: Pokemon Red: Palettes

Hahaha, wow. I went looking for something along these lines myself, but I couldn't find it. I knew 0x30 had to get there somehow if it was previously 0x00 if I had just fainted an enemy Pokemon. :P

I was hoping this would also take care of the Pokeballs that appear at the start of a battle, but it appears not. The "simulation" of a Pokemon with full health just comes from zero-ing out $CF1D and $CF1E in the routine we already modified at 14:65D7 to "simulate" a Pokemon with low health. (of course, it shouldn't accurately be called simulation since the game never runs the health-checking routine at $3DF9)

So do you suppose there's no simpler way to make red Pokeballs appear at the start of a battle than what we've already done?

And do you also think there's no other instance the player's party is displayed other than the start of a battle, which we've already fixed?

Last edited by Danny-E 33 (2012-10-15 01:46:47)


Red Hack: Pokémon Prototype

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

Offline

#66 2012-10-16 02:51:26

comet
Member
Registered: 2012-04-09
Post 22/673

Re: Pokemon Red: Palettes

Link battles come to mind.

Offline

#67 2012-10-16 11:58:58

Danny-E 33
Administrator
Registered: 2012-06-09
Post 176/1,023

Re: Pokemon Red: Palettes

Ah, that's right. When it says "[PLAYER] vs. [PLAYER]" it shows both your parties, I think.
I might look into this, but I was thinking about removing linking capabilities in my hack. I've always found it pretty pointless, especially in an emulator.


Red Hack: Pokémon Prototype

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

Offline

#68 2012-10-27 15:06:58

Danny-E 33
Administrator
Registered: 2012-06-09
Post 218/1,023

Re: Pokemon Red: Palettes

Well I realized there is yet another instance that the Pokeballs are loaded. When you are in a Pokemon Center and you go to your pc and try to switch Pokemon boxes, a Pokeball tile represents which boxes currently have any Pokemon in them.

You said before you put an access breakpoint at 0x8310 but that won't work here becaue the Pokeball tile apparently does not load to the same location in vram as it does for battles.

To find this location, I opened bgb's vram viewer tiles tab and watched the Pokeballs be loaded into vram. Their location in the Pokemon Center is at 0x97F0.

Although this doesn't seem to help much since the only reason you found the location in vram before was to backtrack and find how the palette was loaded. But in this case, there is no palette specifically assigned to the Pokeball tile. Instead is just uses the OW palette of the town you're currently in. The blue water color is always the top half and the color that's different for each town in the bottom half of the Pokeball which often causes it to look quite bizzare.

So my question is, how can I inject a subroutine to cause it to use a different palette while the Pokeballs are being loaded and how do I decide where to fit the routine in?

(there is also the Pokedex where it shows the Pokeball tile to represent which Pokemon you own, but this tile uses the Human/Mews palette so it doesn't look terrible so I've never asked about it. But if you have a simple enough suggestion, I would like to take care of that as well.)


Red Hack: Pokémon Prototype

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

Offline

#69 2012-10-27 18:22:16

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

Re: Pokemon Red: Palettes

Danny-E 33 wrote:

Their location in the Pokemon Center is at 0x97F0.

I think you mean 0x9780 here.

Danny-E 33 wrote:

So my question is, how can I inject a subroutine to cause it to use a different palette while the Pokeballs are being loaded and how do I decide where to fit the routine in?

There are a couple of issues.

First, as you pointed out, there's no specific palette loaded that can be edited. The only choice here is to add some code that loads a palette when the box list is displayed, and cleans up to the original state when the box-list menu is closed.
You could theorically (if you didn't change the pokecenter layout) also simply load a full-screen palette when Bill's PC is accessed because the opened menus cover almost completely the background map (except for the black area on the right, but that area would still be black even if you loaded the red palette); though, this wouldn't be 100% safe, in case you used 4bpp textbox borders.
The former option is formally more accurate, although probably a bit slower too (although, because you'd load the palette right after the game is saved, you shouldn't notice that too much). The latter is less accurate, but maybe a tiny bit easier to implement.

I forgot my second point.

Anyway, you might not know how the SGB palette features work. Palette, as well as the other SGB feature you can implement in a GB game, are "activated" by sending packets to the SNES system following a well defined procedure. For indexed palette (that is what you are interested in) you have to send a PAL_SET packet (plus a ATTR_BLK packet if you're going to specify a specific area of the screen, instead of unaccurately target the whole screen). I wrote some routine that did something similar to what you're trying to do, in Wood (the two very first screens that preceed the copyright screen) but right now I don't exactly remember the various addresses. I'll give it a look tomorrow and report back here.

Meanwhile you might be interested in reading about SGB packets in the pseudo-official manual around pages 140+ and 152+.

Offline

#70 2012-10-28 01:49:58

Danny-E 33
Administrator
Registered: 2012-06-09
Post 219/1,023

Re: Pokemon Red: Palettes

Sawakita wrote:

I think you mean 0x9780 here.

Oh, yeah. That's what I meant. Well that's embarassing.

Sawakita wrote:
Danny-E 33 wrote:

So my question is, how can I inject a subroutine to cause it to use a different palette while the Pokeballs are being loaded and how do I decide where to fit the routine in?

There are a couple of issues.

First, as you pointed out, there's no specific palette loaded that can be edited. The only choice here is to add some code that loads a palette when the box list is displayed, and cleans up to the original state when the box-list menu is closed.
You could theorically (if you didn't change the pokecenter layout) also simply load a full-screen palette when Bill's PC is accessed because the opened menus cover almost completely the background map (except for the black area on the right, but that area would still be black even if you loaded the red palette); though, this wouldn't be 100% safe, in case you used 4bpp textbox borders.
The former option is formally more accurate, although probably a bit slower too (although, because you'd load the palette right after the game is saved, you shouldn't notice that too much). The latter is less accurate, but maybe a tiny bit easier to implement.

Well, since it is currently set up to just use one palette for the whole screen at the time, it sounds simpler to me to just change what palette that is and then change it back and let it apply for the whole screen. Rather than create specific exceptions and isolating parts of the screen. But I'm sure my opinion doesn't count for much since I don't know what I'm talking about.

Sawakita wrote:

Anyway, you might not know how the SGB palette features work. Palette, as well as the other SGB feature you can implement in a GB game, are "activated" by sending packets to the SNES system following a well defined procedure. For indexed palette (that is what you are interested in) you have to send a PAL_SET packet (plus a ATTR_BLK packet if you're going to specify a specific area of the screen, instead of unaccurately target the whole screen). I wrote some routine that did something similar to what you're trying to do, in Wood (the two very first screens that preceed the copyright screen) but right now I don't exactly remember the various addresses. I'll give it a look tomorrow and report back here.

Meanwhile you might be interested in reading about SGB packets in the pseudo-official manual around pages 140+ and 152+.

Yeeaah, I didn't understand much of that. I would like to learn alot more about how handling palettes works and how different palettes are assigned to different parts of the screen, like battles and the title screen. Not really for accomplishing any tasks, I would just like to have the extra knowledge.
I start taking a look at that manual.


Red Hack: Pokémon Prototype

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

Offline

#71 2012-10-28 16:30:05

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

Re: Pokemon Red: Palettes

Danny-E 33 wrote:

Well, since it is currently set up to just use one palette for the whole screen at the time, it sounds simpler to me to just change what palette that is and then change it back and let it apply for the whole screen. Rather than create specific exceptions and isolating parts of the screen. But I'm sure my opinion doesn't count for much since I don't know what I'm talking about.

As I said, recolouring the whole screen instead of just a small area would be an issue only if you modified textbox borders to be 2bpp (by default, they're 1bpp). If it's not your case you can recolour the whole screen as well: this reduces the overhead of defining a custom ATTR_BLK packet, which is the packet that affects how colours are arranged on the screen (while in GBC each tile in VRAM is bound with their own palette, SGB colours the screen, which means a tile's colour depends on where it is located on the screen).


Danny-E 33 wrote:

Yeeaah, I didn't understand much of that.

Sorry, I was a bit in a rush when I wrote that post, I didn't express concepts very clearly.


Anyway, let's try to get an overview of how SGB features are handled.

There's a routine at 1c:5feb that can send any kind of SGB packet using the I/O ports mapped in RAM:$FF00 (this normally gets the joypad inputs, but works as "SGB bridge" too, through a specific protocol).

SendSGBPack: ;$5feb
;check number of packages
    ld a,[hl]
    and a,$07
    ret z
    ld b,a
.loop2\@
    push bc
    ld a,$01
    ld [$fff9],a
    xor a
    ld [$ff00],a
    ld a,$30
    ld [$ff00],a
;save number of packages
    ld b,$10
.loop1\@
;set bit counter (8 bits per byte)
    ld e,$08
    ld a,[hli]
    ld d,a
.loop0\@
    bit 0,d
    ld a,$10
    jr nz,.next0\@
    ld a,$20
.next0\@
    ld [$ff00],a
    ld a,$30
    ld [$ff00],a
    rr d
    dec e
    jr nz,.loop0\@
    dec b
    jr nz,.loop1\@
    ld a,$20
    ld [$ff00],a
    ld a,$30
    ld [$ff00],a
    xor a
    ld [$fff9],a
    call Wait7000
;check if there are more packages
    pop bc
    dec b
    ret z
    jr .loop2\@

;...

Wait7000: ;$614a
    ld de,$1b58    ; = 7000
.loop\@
    nop
    nop
    nop
    dec de
    ld a,d
    or e
    jr nz,.loop\@
    ret

To send a SGB packet you call SendSGBPack routine after loading the pointer to the packet into HL register.

SGB allows at most four different palettes to be active at each time. SGB palettes packets can be of different types:

  • You can load two palettes specifying the four colours of each (PAL_01, PAL_23, PAL_03, PAL_12 fall under this type. Each of these packets loads two palettes, which position you can tell by their name).

  • You can load a set of at most 512 palettes at the beginning of the game for later use, and each time you want to load one of those palettes you send a packet where you specify the ID of that palette (each ID is 9-bit large, although it requires two whole bytes in PAL_SET packets). This is the system used in Red/Blue (Gold/Silver, which provides SGB features, uses the former type of packets, IIRC).

Here is an example (from pokewood) of SGB PAL_SET packet (send palette IDs to load):

PAL_SET_Info:
    SGBpack PAL_SET,1
    dw PAL_REDMON
    dw PAL_GREENMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw 0,0,0
    db 0

"dw" and "db" mean respectively "define word" (i.e. 16 bit value) and "define byte" (8 bit value).

These are the SGBpack macro, SGB packet constants definitions:

;1st value is command
;2nd value is packages number
SGBpack: MACRO
    db \1 << 3 + \2
    ENDM

;SGB constants for commands
PAL_01        EQU $00
PAL_23        EQU $01
PAL_03        EQU $02
PAL_12        EQU $03
ATTR_BLK      EQU $04
PAL_SET       EQU $0A
PAL_TRN       EQU $0B
DATA_SND      EQU $0F
MLT_REQ       EQU $11
CHR_TRN       EQU $13
PCR_TRN       EQU $14
MASK_EN       EQU $17

(You can find PAL_BLUEMON, PAL_REDMON, etc. definitions in pokered disassembly's constants.asm)

This is the same packet as binary data:

PAL_SET_Info:
51 12 00 16 00 11 00 11 00 00 00 00 00 00 00 00

In my case I needed an ATTR_BLK packet too, which looks like this (percentage prefix means base-2, the same way 0x prefix mean base-16):

ATTR_BLK_Info:
    SGBpack ATTR_BLK,1
    db 1
    db 3,%01010101
    db 0,13,19,17
    db 0,%00000000
    db 0,0,0,0
    db 0,0

Corresponding binary form:

ATTR_BLK_Info:
21 01 03 55 00 0d 13 11 00 00 00 00 00 00 00 00

Here's the end result:
23210140.png

Another example of ATTR_BLK is the battle screen one:

ATTR_BLK_01:    ;$61b5
;In-battle
    SGBpack ATTR_BLK,2
    db 5
    db 7,%00001010
    db 0,12,19,17
    db 3,%00000101
    db 1,0,10,3
    db 3,%00000000
    db 10,7,19,10
    db 3,%00001010
    db 0,4,8,11
    db 3,%00001111
    db 11,0,19,6

Which defines something approximately like this "ASCII art":

; - - - - - - - - - - - - - - - - -
;| |                 |             |
;| |                 |             |
;| |_ _ _ _ _ _ _ _ _|             |
;|                                 |
;|                                 |
;|                                 |
;|                                 |
;|                _ _ _ _ _ _ _ _  |
;|               |               | |
;|               |               | |
;|               |_ _ _ _ _ _ _ _| |
;|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
;|                                 |
;|                                 |
;|                                 |
;|                                 |
;|                                 |
;|                                 |
; - - - - - - - - - - - - - - - - -

An ATTR_BLK, by the way, specifies which palette (among the ones currently loaded) is assigned to each area.


TL;DR
So, what you should need is define a PAL_SET packet with the color you want, somewhere in bank 0x1C. Right before the Bill's box list opens you inject your code where you load the pointer, that points to your custom PAL_SET packet, in HL and call the routine that sends SGB packets (1c:5feb). Likewise, when the box-list is closed you reload the map's specific palette.

The game as is, provides a set of routines (addressable by ID, since they are listed in a pointer table) that load PAL_SET and ATTR_BLK for all the needs (in-battle, overworld, town-map, etc.). To call one of these routines you load the predefined routine ID into b (for example the one that loads overworld-map-specific packets is 0x09) and call routine 0x3def, like this:

; Launch predefined PAL_SET + ATTR_BLK packet sending routine
    ld b, 9
    call $3def

I've not tried this solution myself, but it should work. Feel free to point out things that are unclear or wrong.

Note: In pokewood repository you can find most of the SGB stuff disassembled (under «SECTION "Bank1C"» of "pokewood.asm"). Be aware, though, that most of that stuff has been minorly or majorly modified and might not correspond to the original game's code.
Note 2: In BGB, if you open the SGB packets window before starting the game, you can monitor the packets sent by the game.

Last edited by Sawakita (2012-10-28 16:35:04)

Offline

#72 2012-10-31 04:11:10

Danny-E 33
Administrator
Registered: 2012-06-09
Post 224/1,023

Re: Pokemon Red: Palettes

Oh god... I would love to say I understood it all, but that would be a lie..
I'm afraid that your post and the programming manual are so full of vocabulary that I am unfamiliar with and I pretty much couldn't follow along on anything.

I guess, here are my biggest problems that I need clerification on to begin understanding.
What exactly does the manual mean with the "command ATTR_BLK" and what does it even mean by command?
What exactly constitutes a "package"?
What do you mean when you say "send a package"?
And what is PAL_SET? Is that another command?
Oh, and what are you reffering to with the ram's I/O ports? By "ports" do you mean the game communicating with the GameBoy?
I also didn't understand the SendSGBPack routine you provided at all. It might help if you added more comments. Like the several ram locations that are referenced and adding the purpose of specific chunks of code.

Also, are you certain SGBs can only support 4 palettes? BGB showed Red supporting 8, while a GBC game like GSC used 16..


Red Hack: Pokémon Prototype

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

Offline

#73 2012-10-31 05:49:11

539/700

Re: Pokemon Red: Palettes

Danny-E 33 wrote:

What exactly does the manual mean with the "command ATTR_BLK" and what does it even mean by command?

List of SGB commands

Layout of an ATTR_BLK packet

Danny-E 33 wrote:

What exactly constitutes a "package"?

He means “packet.” In computing, a packet is a few bytes, always of some standard structure, usually in transit (in this case, the transit being from the Game Boy CPU on the Super Game Boy cart to the SNES CPU on the SNES).

Danny-E 33 wrote:

What do you mean when you say "send a package"?

Remember what the Super Game Boy is: it is a Game Boy, except that the video output goes to the SNES cartridge slot instead of directly to a screen. Note that only simple video data goes through the cartridge slot, not commands telling the SNES how to manipulate graphics/sound/input. So how then can we send command packets from Pokémon (stored in memory on the SGB CPU) to the SNES, if no CPU registers or memory are shared between the two CPUs?

The typical way is to use a channel that’s shared between the SGB and the SNES: the joypad. On the Game Boy, this is accessible by writing to $FF00 (it’s not actually memory, but a memory‐mapped I/O port, as is most anything from $FF00 to $FF7F). So we send a packet of data to the SNES, containing the SGB command followed by a few bytes of data specific to each command, by toggling bits in the joypad register. Here is an explanation of the process.

#74 2012-10-31 15:29:24

Danny-E 33
Administrator
Registered: 2012-06-09
Post 228/1,023

Re: Pokemon Red: Palettes

So, are SGB packets responsible for more than just palettes? Do they handle other communication between the CPU and and SNES cartridge for the rest of the graphics?

And I'll have to take a look at all those links when I get home tonight. The school's internet security blocked all of them.. :P


Red Hack: Pokémon Prototype

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

Offline

#75 2012-10-31 22:41:44

Danny-E 33
Administrator
Registered: 2012-06-09
Post 230/1,023

Re: Pokemon Red: Palettes

Oh boy. That's alot of information...
So this is supposed to describe the process of sending a packet.

SGB Command Packet Transfers 

Command packets (aka Register Files) are transferred from the gameboy to the SNES by using P14 and P15 output lines of the JOYPAD register (FF00h), these lines are normally used to select the two rows in the gameboy keyboard matrix (which still works).

Transferring Bits
A command packet transfer must be initiated by setting both P14 and P15 to LOW, this will reset and start the SNES packet receiving program. Data is then transferred (LSB first), setting P14=LOW will indicate a "0" bit, and setting P15=LOW will indicate a "1" bit. For example:
       RESET 0   0   1   1   0   1   0
  P14  --_---_---_-----------_-------_--...
  P15  --_-----------_---_-------_------...

 
Data and reset pulses must be kept LOW for at least 5us. P14 and P15 must be kept both HIGH for at least 15us between any pulses.
Obviously, it'd be no good idea to access the JOYPAD register during the transfer, for example, in case that your VBlank interrupt procedure reads-out joypad states each frame, be sure to disable that interrupt during the transfer (or disable only the joypad procedure by using a software flag).

Transferring Packets
Each packet is invoked by a RESET pulse, then 128 bits of data are transferred (16 bytes, LSB of first byte first), and finally, a "0"-bit must be transferred as stop bit. The structure of normal packets is:
   1 PULSE Reset
   1 BYTE  Command Code*8+Length
  15 BYTES Parameter Data
   1 BIT   Stop Bit (0)

 
The above 'Length' indicates the total number of packets (1-7, including the first packet) which will be sent, ie. if more than 15 parameter bytes are used, then further packet(s) will follow, as such:
   1 PULSE Reset
  16 BYTES Parameter Data
   1 BIT   Stop Bit (0)

 
By using all 7 packets, up to 111 data bytes (15+16*6) may be sent.
Unused bytes at the end of the last packet must be set to zero.
A 60ms (4 frames) delay should be invoked between each packet transfer.

But again. The vocabulary barrier. I can't begin to understand cause I don't know what all the bits and peices are. If I knew all the right terms, hopefully lightbulbs would start to go off.

What are P14 and P15?
How exactly is the joypad register getting involved in this?
What are low and high?
What are pulses?
What does LSB mean?
And I still don't understand where exactly a packet is supposed to come from..

Sorry for all the question, but everyone had to learn at some point I suppse..


Red Hack: Pokémon Prototype

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

Offline

Board footer

Powered by FluxBB