Other Beginning Hacking (Gen 1)

Started by Imafruitbat September 27th, 2015 10:52 AM
  • 11418 views
  • 77 replies
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
So I am new to the forum and had some specific questions about getting into the hacking game. I've noticed there is a lot of support for the advance series and later, but a lot of the support for the GBC series is either defunct or non-existent.

I have a handful of programs for my project: Pokemap 1.2, several of Swampert Tools programs, and some other various programs that I can't get to run. That said, here's what I'm trying to find out:

Pokemap seems like it's going to be my bread and butter for adding new NPCs and such, but can't seem to find any support on the program outside of it's readme. I can easily add new NPCs, but I can't figure how to edit their dialog. One of the primary concepts I want to play with is character and story immersion, but I can't exactly do that without understanding what I should be doing. The tutorials I see for the advance editors make text editing look pretty straightforward, but I've only gotten as far as "text string number" which I assume refers to a labelled text set somewhere in the game code. I don't know where to find this list of numbers or how to edit the text associated with them. It should be possible via Pokemap if ye olde "World Famous Talking Cactus" is anything to go by.

If anyone knows where I can find some more in depth resources for Pokemap or tutorials or some such, I'd be most grateful. If there is a program that is more user friendly for editing text in GBC I would also appreciate that, as I'm not yet attached to any particular program. There are a couple of other things I want to do as well, but this is Priority Number 1 right now in terms of my concept.


Thanks guys! :)

As an aside, I don't really have much interest in modding Advance series, as my project goals are very minimalist and I just can't get over the nostalgia factor or the black and white.

Deokishisu

Mr. Magius

Male
If I'm online, it's a safe bet I'm at a computer.
Seen 6 Hours Ago
Posted 6 Hours Ago
948 posts
16.4 Years
There are several hackers around that are still making really amazing projects with the Gen One and Two games. Like, they're the real deal compared to most of us GBA hackers. They may be willing to help you if you start a project and hit a major snag that you just can't figure out.

If you're hacking Red, there's a disassembly available that gives you pretty much full control of what you want the game to do if you've got the know-how to manipulate it. There's a tutorial (along with a link to the disassembly itself) right here.

I believe that there is a Crystal disassembly in progress, but I'm not entirely sure what the status is on that. You may want to look into it if you aren't going for an RBY hack.

Other than all of those links and the info about the disassembly, I unfortunately can't offer anything else. My knowledge is more in line with the third generation games. I wish you luck though! We seriously need more Gen 1 and 2 hacks around here.
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
Thanks, I've got pokered and will look into the programs associated with editing the ASMs and such. Unless I'm misunderstanding and Pokered is the program I need for ASM files and the disassembly... Either way, I've dug into Poketext enough to have a general idea where everything is. I'm just not sure if saving changes through that program saves them in the rom directly. Only one way to find out I guess!

Thanks a bunch!

miksy91

Dark Energy is back in action! ;)

Male
Finland
Seen September 6th, 2019
Posted August 30th, 2019
1,480 posts
13.7 Years
pokered is not a program, it's disassembly. What this means is that you can make your "own copy" of that disassembly project by forking it and then edit that copy for yourself. You can write all the code and data with any kind of a text editor - like Notepad if you're using Windows.

You should join Skeetendo Inc. and check the documentation there and what disasembly is all about.
Pokémon Dark Energy
Some ROM hacking related stuff
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
There are a few questions I have that I'm no huge rush to fix (I have plenty of text to edit!), but am curious about:

I tried removing some of the warp points in Viridian City, but it didn't make the building doors inoperable, in fact, it just changed which building I exited from, no matter the building I was in. How would I go about (b)locking a door to a building with a notice Viridian's Gym?

I also thought I'd be able to add more NPCs using Pokemap, but apparently I can only edit ones already there (and limited at that). I've attached 2 pictures of what I'm working with, and hopefully an explanation of the some of the "commands"(?) like what's up with the $ everywhere.

I'll be posting this to Skeetendo, since it's dedicated Gen 1 and 2, but it seemed pretty empty when I checked it for resources. EDIT: I take that back, there are two Skeetendos, and one is certainly not empty.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
You can add a new NPC with pokered easily by just adding a new object (person) and incrementing the person counter. For example:
object SPRITE_OAK, $5, $2, STAY, DOWN, $5 ; person
SPRITE_OAK is the NPC's sprite.

$5, $2 are x and y coordinates respectively, from the top left corner of the map. The $ symbol is to denote that the number is in hexadecimal, just like % denotes a binary number. So for example $a is the same as 10, and $5 is the same as 5.

STAY, DOWN means that the object is static and that it is looking down by default. Use WALK, $0 if you want the person to move around (also WALK, $1 for only vertical movements and WALK $2 for only horizontal movements), and use STAY, NONE if you want the person to rotate its facing or if it's only an object with a single facing defined (e.g. ball or dex sprites).

The last $5 is the text/script id. In general it should be the same as the object number for simplicity, unless you want to use the same script for multiple objects.

To remove a warp you have to remove both its entry in "warps" and in "warp to". If you remove a warp only from one place you will shift the other warps so they will no longer warp to where they should.

Let's see how warps work. This is the first warp in Pallet Town:
; warps
	db $5, $5, $0, REDS_HOUSE_1F
(...)
; warp-to
	EVENT_DISP PALLET_TOWN_WIDTH, $5, $5 ; REDS_HOUSE_1F
(...)
REDS_HOUSE_1F is the connected map.

$5, $5 are the x,y coordinates where the warp is at. Note that unless the warp is in a tile whose collision allows warping (e.g. a door), it won't work.

$0 is the "warped to" id within the destination map. Red's House 1F has two warps, one to Pallet Town and one to your room. $0 refers to the first warp (Pallet) and $1 would refer to the second (your room). If you checked out the Red's House 1F file you'll see how its first warp entry warps to Pallet Town so that the two connected warps match.

PALLET_TOWN_WIDTH is the connected map's width, and $5, $5 are the x,y coordinates again.

A warp could also look like this:
; warps
	db $b, $4, $2, $ff
(...)
; warp-to
	EVENT_DISP OAKS_LAB_WIDTH, $b, $4
(...)
In this case we have $ff instead of the connected map id. $ff will be interpreted as the last map we were at. You can use this when it's certain that coming back to the previous map is the only possibility. For example if you go through a warp in Oak's lab the only option is that you're warping to Pallet Town, which is the map you'll be always coming from. But if you're at your house, you could be coming from your room upstairs and then exit through the door, so you can't use $ff here.
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
Thanks! That helped heaps!

I'm still having trouble getting the warps to do what I want (which is literally nothing, I want the doors to appear locked). I tested it with Blue's House; removing the warp and warp-to in pallettown.asm, but that bugged leaving Red's House. It did the same thing when I removed the warp and warp-tos for the blueshouse.asm. What am I missing?

Are there any limits on how many events (NPCs or otherwise) to a map?
Do I need to worry about adding pointers for new NPCs? If not, what do they do for the original NPCs?

I'm also trying to find Oak's response text to naming the player and rival, as it doesn't seem to be with the rest of oakspeech.asm.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
I'm still having trouble getting the warps to do what I want (which is literally nothing, I want the doors to appear locked). I tested it with Blue's House; removing the warp and warp-to in pallettown.asm, but that bugged leaving Red's House.
You probably didn't update the wrap number byte from 3 to 2. This will just solve leaving red's house though, but Oak's lab warp will still be pointing to pallet town's third warp (warp id $2) which no longer exists. You'll have to do:
OaksLabObject: ; 0x1d40a (size=88)
	db $3 ; border block

	db $2 ; warps
	db $b, $4, $1, $ff
	db $b, $5, $1, $ff
In short, whenever you remove a warp from a map, keep an eye out for all the other maps that have a warp to the map you just edited.

Are there any limits on how many events (NPCs or otherwise) to a map?
I'm not sure if it's 15 plus your own, since the sprite data buffers can store up to 16 entries. It might be lower though. You also can't have more than 10 sprites (objects) displaying at a time.

Do I need to worry about adding pointers for new NPCs? If not, what do they do for the original NPCs?
A new NPC involves a new text pointer or at least an id that references an existing one. The text id is the sixth byte/argument of the object macro (also, always the last byte for non-trainer non-item objects). You should proceed by adding your new objects after the last one for simplicity and using the first text id available for the same reason. For example, for Pallet Town that'd be $8 (there are also four signs that use $4 to $7). Then you'd add an entry in the text pointers in scripts/pallettown.asm (e.g. PalletTownText8), and defining it like:

PalletTownText8: 
	TX_FAR _PalletTownText8
	db "@"
And then write the actual text in text/maps/pallettown.asm.

I'm also trying to find Oak's response text to naming the player and rival, as it doesn't seem to be with the rest of oakspeech.asm.
Probably at text/maps/oakslab.asm
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
Can confirm that it's not there. I'll dig around some more. Thanks for the pointers on warps! I knew I was missing something!
Oh, my bad that's from the intro.

You can always do a quick search:
https://github.com/iimarckus/pokered/search?utf8=%E2%9C%93&q=first%2C+what+is+your+name&type=Code

If you are looking for the script, it's here: https://github.com/iimarckus/pokered/blob/master/engine/oak_speech2.asm
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
You probably didn't update the wrap number byte from 3 to 2. This will just solve leaving red's house though, but Oak's lab warp will still be pointing to pallet town's third warp (warp id $2) which no longer exists. You'll have to do:
OaksLabObject: ; 0x1d40a (size=88)
	db $3 ; border block

	db $2 ; warps
	db $b, $4, $1, $ff
	db $b, $5, $1, $ff
In short, whenever you remove a warp from a map, keep an eye out for all the other maps that have a warp to the map you just edited.
Could you go into a little more detail here? I'm still having some trouble. I'm assuming the 3rd $# is the "warp number" (in red above), but is it continuous between maps or does the count start over from 0/1 at every new map? Reason I ask is that I tried this in Pewter City, but the numbers weren't consistent (several 0s and one at 2). Is there a consistent change I'm aiming for with these? Am I just subtracting 1 from them, or is it something else?

Add: I've also hit another minor snag.. Pokemap can edit my ROM correctly, but it doesn't save the data if I compile a new red ROM. I understand why, as it only edits the ROM and not the files that are being compiled into the new one, but it's a bit of a pain. I've also figured out a way around disabling the warp points for pokemon centers. It's not as immersive, but it does what I need and I can work around that.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
Clearly, those two warps belong to Oak's Lab <-> Pallet Town, as $ff warps to the last map the player was at, and the only option is that we came from pallet town.

Now, the two numbers in red were originally $2. (I changed them to $1 following an example you suggested). They are $2 because the warp in the $2 position (that is, in the 3rd position) in pallet town refers to oak's lab. Indeed:

PalletTownObject: ; 0x182c3 (size=58)
(...)
	db $3 ; warps
	db $5, $5, $0, REDS_HOUSE_1F
	db $5, $d, $0, BLUES_HOUSE
	db $b, $c, $1, OAKS_LAB
(...)
	EVENT_DISP PALLET_TOWN_WIDTH, $5, $5 ; REDS_HOUSE_1F
	EVENT_DISP PALLET_TOWN_WIDTH, $5, $d ; BLUES_HOUSE
	EVENT_DISP PALLET_TOWN_WIDTH, $b, $c ; OAKS_LAB
If you do this:
PalletTownObject: ; 0x182c3 (size=58)
(...)
	db $2 ; warps
	db $5, $5, $0, REDS_HOUSE_1F
	db $b, $c, $1, OAKS_LAB
(...)
	EVENT_DISP PALLET_TOWN_WIDTH, $5, $5 ; REDS_HOUSE_1F
	EVENT_DISP PALLET_TOWN_WIDTH, $b, $c ; OAKS_LAB
The warp that refers to oak's lab is no longer in the 3rd position (position $2), but in the 2nd position (position $1).

So in order to reflect that in the oak's lab file, you change the two $2's to $1's:

OaksLabObject: ; 0x1d40a (size=88)
	db $3 ; border block

	db $2 ; warps
	db $b, $4, $1, $ff
	db $b, $5, $1, $ff
Add: I've also hit another minor snag.. Pokemap can edit my ROM correctly, but it doesn't save the data if I compile a new red ROM. I understand why, as it only edits the ROM and not the files that are being compiled into the new one, but it's a bit of a pain. I've also figured out a way around disabling the warp points for pokemon centers. It's not as immersive, but it does what I need and I can work around that.
You'll have to dump them. You can use another pokered ROM where you only change the maps, and then you can replace the map block data of the maps in pokered with binary includes of that ROM using INCBIN, like this:

INCBIN "otherrom.gbc", $60000, $500
You just need to know the start address and the size (or the end address) of the maps.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
Is it possible for moves to be edited with multiple effects? Or is it one effect per move, as it appears to be in moves.asm?
You could create a new move effect that is a combination of two or more existing effects, but you can't have a move point to two different move effect id's.
Which combination of multiple effects did you have in mind?
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
You could create a new move effect that is a combination of two or more existing effects, but you can't have a move point to two different move effect id's.
Which combination of multiple effects did you have in mind?
I was just trying to fix Tri Attack so that it has a chance to burn, freeze or paralyze.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
I was just trying to fix Tri Attack so that it has a chance to burn, freeze or paralyze.
That would require a small edit in the FreezeBurnParalyzeEffect function.

First you create a new move effect in move_effect_constants.asm (after the last one).
	const TRI_ATTACK_EFFECT  ; $57
Then you add that effect to MoveEffectPointerTable in core.asm (after the last one).
	 dw TriAttackEffect             ; TRI_ATTACK_EFFECT
Find out if you have to add the new effect to one of the effect arrays at the top of core.asm (not the case for this effect)

Now here's the hardest part, implementing the move effect itself. Luckily, most of it is already done since you already have the three possible effects working separately under the same effect handler (FreezeBurnParalyzeEffect).

Put this right before the FreezeBurnParalyzeEffect routine (line 7401 of core.asm in current clean pokered)

TryAttackEffect:
   ld b, BURN_SIDE_EFFECT1
   ld a, [hRandomSub] ; grab a random number
   cp 85 ; 85 / 256 chance = 33%
   jr c, .gotStatusEffect
   inc b ; FREEZE_SIDE_EFFECT
   cp 170 ; (170-85) / 256 chance = 33%
   jr c, .gotStatusEffect
   inc b ; PARALYZE_SIDE_EFFECT1 ; remaining 33%
.gotStatusEffect
   ld a, b
   ld [wPlayerMoveEffect], a
; fallthrough to FreezeBurnParalyzeEffect
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
I was going to edit this and ask about Focus Energy, as I'm trying to implement it as originally intended. I've checked here
http://glitchcity.info/wiki/index.php/Focus_Energy_glitch
but can't seem to find that section of code. I found something like it in core.asm, but it doesn't look like there are any numbers for me to correct. And I know this has already been done in most Gen 1 hacks, which is why I'm frustrated that searching resources yielded little to nothing. Or maybe I just can't see.

Thanks for the walkthrough on Tri Attack. I appreciate your time.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
Remove srl b at line 4697
Change line 4713 to jr z, .noFocusEnergyUsed
Replace lines 4715 to 4720 with:
sla b
jr c, .guaranteedCritical
sla b
jr c, .guaranteedCritical
Then between lines 4745 (ret nc) and 4746 (ld a, $1) add the label .guaranteedCritical

Basically the sla instruction causes a left shift leading to a multiplication by 2 while the srl instruction causes a right shift leading to a division by 2. By removing a srl b and a sla b for the non-focus energy case we leave it unaffected, while by replacing the two srl b affecting the focus energy used case with sla b, we make the crit raite four times higher instead of quartering it. jr c, .guaranteedCritical are there to make sure the value does not overflow.
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
Basically the sla instruction causes a left shift leading to a multiplication by 2 while the srl instruction causes a right shift leading to a division by 2. By removing a srl b and a sla b for the non-focus energy case we leave it unaffected, while by replacing the two srl b affecting the focus energy used case with sla b, we make the crit rate four times higher instead of quartering it. jr c, .guaranteedCritical are there to make sure the value does not overflow.
I'm not sure I would have figured that out on my own. Thank's a heap!

When adding the label .gauranteedCritical some of my line numbers are different. Should I be more concerned with where they are in the code than with the line number they fall on? Is there a bit of code that should come before it? I see a lot of .variouslines that follow a "jr c" or "jr z".

Spoiler:
CriticalHitTest: ; 3e023 (f:6023)
xor a
ld [wCriticalHitOrOHKO], a
ld a, [H_WHOSETURN]
and a
ld a, [wEnemyMonSpecies]
jr nz, .asm_3e032
ld a, [wBattleMonSpecies]
.asm_3e032
ld [wd0b5], a
call GetMonHeader
ld a, [wMonHBaseSpeed]
ld b, a
ld a, [H_WHOSETURN]
and a
ld hl, wPlayerMovePower
ld de, wPlayerBattleStatus2
jr z, .calcCriticalHitProbability
ld hl, wEnemyMovePower
ld de, wEnemyBattleStatus2
.calcCriticalHitProbability
ld a, [hld] ; read base power from RAM
and a
ret z ; do nothing if zero
dec hl
ld c, [hl] ; read move id
ld a, [de]
bit GettingPumped, a ; test for focus energy
jr z, .nofocusEnergyUsed ; bug: using focus energy causes a shift to the right instead of left,
sla b
jr c, .guaranteedCritical
sla b
jr c, .guaranteedCritical


.Loop
ld a, [hli] ; read move from move table
cp c ; does it match the move about to be used?
jr z, .HighCritical ; if so, the move about to be used is a high critical hit ratio move
inc a ; move on to the next move, FF terminates loop
jr nz, .Loop ; check the next move in HighCriticalMoves
srl b ; /2 for regular move (effective (base speed / 2))
jr .SkipHighCritical ; continue as a normal move
.HighCritical
sla b ; *2 for high critical hit moves
jr nc, .noCarry
ld b, $ff ; cap at 255/256
.noCarry
sla b ; *4 for high critical move (effective (base speed/2)*8))
jr nc, .SkipHighCritical
ld b, $ff
.SkipHighCritical
call BattleRandom ; generates a random value, in "a"
rlc a
rlc a
rlc a
cp b ; check a against calculated crit rate
ret nc ; no critical hit if no borrow
jr nc, .guaranteedCritical
ld a, $1
ld [wCriticalHitOrOHKO], a ; set critical hit flag
ret


That's what I have from line 4684 to line 4745 since editing, if it helps.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
Remove in red, add in green:

CriticalHitTest: ; 3e023 (f:6023)
xor a
ld [wCriticalHitOrOHKO], a
ld a, [H_WHOSETURN]
and a
ld a, [wEnemyMonSpecies]
jr nz, .asm_3e032
ld a, [wBattleMonSpecies]
.asm_3e032
ld [wd0b5], a
call GetMonHeader
ld a, [wMonHBaseSpeed]
ld b, a
ld a, [H_WHOSETURN]
and a
ld hl, wPlayerMovePower
ld de, wPlayerBattleStatus2
jr z, .calcCriticalHitProbability
ld hl, wEnemyMovePower
ld de, wEnemyBattleStatus2
.calcCriticalHitProbability
ld a, [hld] ; read base power from RAM
and a
ret z ; do nothing if zero
dec hl
ld c, [hl] ; read move id
ld a, [de]
bit GettingPumped, a ; test for focus energy
jr z, .nofocusEnergyUsed ; bug: using focus energy causes a shift to the right instead of left,
sla b
jr c, .guaranteedCritical
sla b
jr c, .guaranteedCritical

.noFocusEnergyUsed
ld hl, HighCriticalMoves ; table of high critical hit moves

.Loop
ld a, [hli] ; read move from move table
cp c ; does it match the move about to be used?
jr z, .HighCritical ; if so, the move about to be used is a high critical hit ratio move
inc a ; move on to the next move, FF terminates loop
jr nz, .Loop ; check the next move in HighCriticalMoves
srl b ; /2 for regular move (effective (base speed / 2))
jr .SkipHighCritical ; continue as a normal move
.HighCritical
sla b ; *2 for high critical hit moves
jr nc, .noCarry
ld b, $ff ; cap at 255/256
.noCarry
sla b ; *4 for high critical move (effective (base speed/2)*8))
jr nc, .SkipHighCritical
ld b, $ff
.SkipHighCritical
call BattleRandom ; generates a random value, in "a"
rlc a
rlc a
rlc a
cp b ; check a against calculated crit rate
ret nc ; no critical hit if no borrow
jr nc, .guaranteedCritical
ld a, $1
ld [wCriticalHitOrOHKO], a ; set critical hit flag
ret


The difference between jr nc, .guaranteedCritical and .guaranteedCritical is that the former is a jump instruction while the second is a label. Labels are used so that when you want to use a jump or call instruction you don't have to figure out the hexadecimal address of where you want to jump to. The assembler will translate every label to the numeric position it is at. However you cannot reference a label in an instruction without creating the label itself, because in that case the assembler won't understand that unexisting label.
Male
Spain
Seen November 7th, 2021
Posted July 1st, 2018
170 posts
9.4 Years
Labels like .noFocusEnergyUsed cannot be tabulated like the rest of the code. Otherwise they are interpreted as a instruction, or failing that, as a macro.

Also make sure that .noFocusEnergyUsed and jr z, .nofocusEnergyUsed (five lines above) use both either a capitalized or uncapitalized 'F' for the word focus.
Seen November 26th, 2016
Posted November 26th, 2016
56 posts
6.8 Years
Labels like .noFocusEnergyUsed cannot be tabulated like the rest of the code. Otherwise they are interpreted as a instruction, or failing that, as a macro.
So how do I get it to be recognized as a label?

I double checked EVERY instance of .nofocusEnergyUsed and .noFocusEnergyUsed to make sure their spelling and instances match. They do match up, and unfortunately still I get exactly the same error.