Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2013-11-03 21:09:59

comet
Member
Registered: 2012-04-09
Post 306/679

Hack Requests

I'm taking requests for small hacks. If there's a tweak you've wanted done in a Game Boy game that you're struggling with, you can recruit me to help.

I prefer helping people learn how to hack themselves but there's only so much one person can do. Others would rather have someone experienced do the hacking part so they can work on content instead of taking time to learn something they think they won't be very good at. Part of this exercise is to show that it's actually pretty easy.

Along with the finished mod I'll include the assets used to make it for those curious or wanting to show off to friends. I'll also post them here. Scale is a factor in how long it'll take to finish. If you're not sure if a request is reasonable just ask.

Offline

#2 2013-11-04 14:42:47

80C
Banned
Registered: 2013-03-16
Post 1,180/1,257

Re: Hack Requests

Yes, there's a tweak I tried but failed tragically.

But I don't want you to do it for me.

I want ask you where the problem could be.

Basically, I've inserted extra screens before the "1995 game freak" logo shows up, and it was (almost) successfull unless the game strangely made the characters of the InfoScreen misplaced.

Technically, I sampled Sawakita's Wood Disassembly documents and modified its code.
There are two screens: the first draws a custom box included in the data with some text inside, the screen could be skipped only with the pression of any button.
The second one is automatic and shows a textbox in the upper part with a few text inside + a Logo in the lower part (Skeetendo's Logo in this case).

This is what I've obtained the first time:

43qa.png

The palette for that first screen didn't showed up, the text was misplaced and the next screen froze the game.
I don't know quite why.

Plus, the other times I've attempted to do it the game directly froze without even loading the screens.

Everything seemed to be correct.

Please, could you let me understand if I've missed something or did something wrong?

Here's the Original code of Sawakita:

FirstInfoScreen:
    ld a,[ff40]
    set 3,a
    ld [ff40],a
    call 3680
    call 36a0
    ld de,MyBorderGFX    ;gfx of up & down arrow
    ld hl,9790
    ld b,(BANK(MyBorderGFX))
    ld c,06
    call 1848
    ld b,BANK(SkeetendoGFX)
    ld de,SkeetendoGFX
    ld hl,9000
    ld c,21
    call 1848
    call ClearScreen
    ld a,%00100111
    ld [ff47],a
    FuncCoord 0,1
    ld hl,Coord
    ld bc,0b10
    call 1922    ;textbox
    FuncCoord 13,1
    ld hl,Coord
    ld bc,0310
    call 1922    ;textbox
    ld de,InfoScreenData
    FuncCoord 1,2
    ld hl,Coord
    ld a,[fff6]
    set 2,a
    ld [fff6],a
    call 1955
    ld c,14
    call Delay
.catchKeyPress\@
    call 3831
    ld a,[ffb5]
    and a
    jr z,.catchKeyPress\@
    ld a,[fff6]
    res 2,a
    ld [fff6],a
    ld bc,0f0f
    ;FuncCoord 2,2
    ;ld hl,Coord
    ;call 18c4
    call ClearScreen
    call Delay3
    ld b,BANK(SET_PAL_InfoScreen2)
    ld hl,(SET_PAL_InfoScreen2)
    call Bankswitch
    FuncCoord 6,3
    ld hl,Coord
    ld bc,030c
    call 1922    ;textbox
    FuncCoord 8,5
    ld hl,Coord
    ld de,HaveFunText
    call 1955
    call Delay3
    call ArrangeSkeetendo
    ld c,5a
    call Delay
    ld a,%00010110
    ld [ff47],a
    call Delay3
    ld a,%00000001
    ld [ff47],a
    call Delay3
    ld a,%00000000
    ld [ff47],a
    call Delay3
    ld b,0c
    call 3def
    ld b,01
    ld hl,4538
    jp Bankswitch
ArrangeSkeetendo:
    FuncCoord 14,4
    ld hl,Coord
    ld de,0014
    ld bc,030b
    xor a
.loop1\@
    push hl
    push bc
.loop0\@
    ld [hli],a
    add a,3
    dec c
    jr nz,.loop0\@
    pop bc
    pop hl
    add hl,de
    dec b
    ld a,b
    and a
    ret z
    ld a,3
    sub b
    jr .loop1\@
MyBorderGFX:
    incbin "Pics//MyBorderGFX.hex"
SkeetendoGFX:
    incbin "Pics//SkeetendoGFX.hex"
InfoScreenData:
    incbin "Texts//FirstInfoScreenData.hex"
HaveFunText:
;"HAVE FUN!"
    db 87,80,95,84,7F,7F,85,94,8D,E7
    TX_NULL

That was the original code done by Sawakita.


Here's the version of the same code adapted for BGB use and with my adresses
IMPORTANT: The adresses of the new screens and stuff + the adress of the custom routine isn't definitive, after the failure I added a few new data near there so I'll need to put it after 0x43900 circa (so there's enought space in the bank for all the stuff, I'll had in mind to use the minor space possible because in the same bank I'll have to put the Pokedex pages data for the new pokemon)

;10:588A

;LoadCopyrightScreen:    ;$588a
    nop
    nop
    ld b,2F                ;BANK(SET_PAL_InfoScreen)
    ld hl,4788            ;SET_PAL_InfoScreen, adress
    call 35D6            ;Bankswitch
    call 6AA0            ;FirstInfoScreen
    ld a,E4
    ld ($ff00+47),a
    ld c,4A
    call 3739            ;Delay


;10:6AA0

;FirstInfoScreen:
    ld a,(ff00+40)
    set 3,a
    ld (ff00+40),a
    call 3680
    call 36A0
    ld de, 6C00            ;MyBorderGFX;gfx of up & down arrow
    ld hl,9790
    ld b,10                ;(BANK(MyBorderGFX))
    ld c,06
    call 1848
    ld b,10                ;BANK(SkeetendoGFX)
    ld de,SkeetendoGFX        ;SkeetendoGFX
    ld hl,9000
    ld c,21
    call 1848
    call 190F            ;Clearscreen
    ld a,27                ;%00100111
    ld (ff00+47),a            ;bg pal
    ;FuncCoord 0,1
    ld hl,C3A1            ;Coord
    ld bc,0B10
    call 1922            ;textbox
    ;FuncCoord 13,1
    ld hl,C4A5            ;Coord
    ld bc,0310
    call 1922            ;textbox
    ld de,InfoScreenData
    ;FuncCoord 1,2
    ld hl,C36B            ;Coord
    ld a,(ff00+f6)
    set 2,a
    ld (ff00+f6),a
    call 1955
    ld c,0E                ;OG ld c,14
    call 3739            ;call Delay

;.catchKeyPress\@
    call 3831
    ld a,(ff00+b5)
    and a
    jr z,6AF3            ;jr z .catchKeyPress\@
    ld a,(ff00+f6)
    res 2,a
    ld (ff00+f6),a
    ld bc,0F0F
    ;FuncCoord 2,2
    ;ld hl,Coord
    ;call 18c4
    call 190F            ;ClearScreen
    call 3DD7            ;Delay3
    ld b,2F                ;OG 1C- BANK(SET_PAL_InfoScreen2)
    ld hl,4790            ;(SET_PAL_InfoScreen2) adress
    call 35D6            ;Bankswitch
    ;FuncCoord 6,3
    ld hl,C41B            ;Coord
    ld bc,030c
    call 1922            ;textbox
    ;FuncCoord 8,5
    ld hl,C445            ;Coord
    ld de,                ;HaveFunText
    call 1955
    call 3DD7            ;Delay3
    call 6B51            ;ArrangeSkeetendo
    ld c,5a
    call 3739            ;Delay
    ld a,16                ;%00010110
    ld (ff00+47),a            ;bg pal
    call 3DD7            ;Delay3
    ld a,01                ;%00000001
    ld (ff00+47),a            ;bg pal
    call 3DD7            ;Delay3
    ld a,00                ;%00000000
    ld (ff00+47),a            ;bg pal
    call 3DD7            ;Delay3
    ld b,0c
    call 3DEF
    ld b,01
    ld hl,4538
    jp 35D6                ;Bankswitch

;6B51; ArrangeSkeetendo:
    ;FuncCoord 14,4
    ld hl,C4BC            ;Coord
    ld de,0014
    ld bc,030b
    xor a

;.loop1\@ ;6B5B
    push hl
    push bc

;.loop0\@ ;6B5D
    ldi (hl),a
    add a,03
    dec c
    jr nz,6B5D                ;jr nz.loop0\@
    pop bc
    pop hl
    add hl,de
    dec b
    ld a,b
    and a
    ret z
    ld a,03
    sub b
    jr 6B5B                ;jr.loop1\@

    nop
    nop

;MyBorderGFX:
    incbin "Pics//MyBorderGFX.hex"

;SkeetendoGFX:
    incbin "Pics//SkeetendoGFX.hex"

;InfoScreenData:
    incbin "Texts//FirstInfoScreenData.hex"

;HaveFunText:
;"HAVE FUN!"
    db 87,80,95,84,7F,7F,85,94,8D,E7
    TX_NULL //(0x50?)

Of course at that time I inserted all the stuff related with screens etc.

Your help for explanation would be really appreciated as well as your credit in my hack (you know which one ;) ).

PS: Of course I'll do all the job for myself, I only need an opinion if there's something wrong.


I left this forum.

Offline

#3 2013-11-04 14:55:25

YORAMRW
Member
From: The Netherlands
Registered: 2013-03-29
Post 890/1,199
Website

Re: Hack Requests

You are going to hack things for other people? That's really kind of you. I think I have something I need help for in the future, and of course I will credit you for something you did for me. :)


Hacks Gameboy 8-bit music in Pokémon Gen I & II, composes 8-bit music in FamiTracker

Offline

#4 2013-11-04 20:57:14

comet
Member
Registered: 2012-04-09
Post 307/679

Re: Hack Requests

80C wrote:

Yes, there's a tweak I tried but failed tragically.

at a glance:

+    ;FuncCoord 1,2
+    ld hl,C36B            ;Coord

this looks like a typo since (1, 2) is $c3b6

you also have lines that bgb wont accept. i dont know if youre resolving these at the time or pasting each line in and bgb is ignoring them

+    ld ($ff00+47),a
+    ld de, 6C00            ;MyBorderGFX;gfx of up & down arrow
-    ld b,BANK(SkeetendoGFX)
-    ld de,SkeetendoGFX
+    ld b,10                ;BANK(SkeetendoGFX)
+    ld de,SkeetendoGFX        ;SkeetendoGFX
=    ld de,InfoScreenData
+    ld de,                ;HaveFunText

youre also using SET_PAL_InfoScreen which is another pokewood thing. i have no way of knowing whether youre using everything from pokewood that you need to (SendPALandATTR and the other custom sgb functions etc). the only crashes i got were from here

+    ld b,2F                ;BANK(SET_PAL_InfoScreen)
+    ld hl,4788            ;SET_PAL_InfoScreen, adress
+    call 35D6            ;Bankswitch
+    ld b,2F                ;OG 1C- BANK(SET_PAL_InfoScreen2)
+    ld hl,4790            ;(SET_PAL_InfoScreen2) adress
+    call 35D6            ;Bankswitch

if its not working out for you, you could have made a mistake copying it over:

SET_PAL_InfoScreen:
    ld hl,PAL_SET_Info
    ld de,ATTR_BLK_Info
    jp SendPALandATTR    ;$6165
SET_PAL_InfoScreen2:
    ld hl,PAL_SET_Info2
    ld de,ATTR_BLK_00
    jp SendPALandATTR    ;$6165
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
PAL_SET_Info2:
    SGBpack PAL_SET,1
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw 0,0,0
    db 0

you should be able to figure out what's missing by following your code in the debugger until something bad happens

Last edited by comet (2013-11-04 22:29:01)

Offline

#5 2013-11-04 23:02:38

Hat
Member
Registered: 2013-02-04
Post 48/118

Re: Hack Requests

The addition of a 4th period of day to GSC, evening roughly opposite to morning, would be interesting. Digimon World (PSX) was like that, it seemed weird that GSC wasn't. A modification like this could then be used for other hacks like with VWFs, colourisations, tileset extensions etc.

Offline

#6 2013-11-04 23:53:42

Vitharix
Member
Registered: 2011-12-29
Post 349/396

Re: Hack Requests

I've always been interested by the idea of including seasons. If anyone has ever played Legend of Zelda: Oracle of Seasons, that's my obvious inspiration. Seems like it wouldn't be too difficult, too. After a certain number of days, a different tileset is displayed in the overworld. That would really be the extent of it aside from the coding involved.

Offline

#7 2013-11-05 12:51:00

Hat
Member
Registered: 2013-02-04
Post 49/118

Re: Hack Requests

Seasons could work nicely with this:

KBM for Prism wrote:

- New Clock system – No longer real time but can keep track of days months and years.

DW again. More possibilities for events, less waiting for them.

Time could be slowed/hastened (DW/Zelda) or skipped (like the 3 years between the RGBY and GSC stories). Time travel would obviously be helpful for Celebi stories.

Offline

#8 2013-11-06 18:19:53

80C
Banned
Registered: 2013-03-16
Post 1,181/1,257

Re: Hack Requests

@Comet

Obviously I didn't put the fist code table I've posted here, because that's specifical for Wood with Wood's adresses.
The codes I used are in the second table.

The second part in which you had crashes is related to Palette Data: my table of palettes is now in bank 2F instead of 1C that's why it crashed in your testing ROM.

I thought ld hl,4790 was the adress of the palette you wish use, maybe the problem is in there.


I left this forum.

Offline

#9 2013-11-09 01:16:41

comet
Member
Registered: 2012-04-09
Post 308/679

Re: Hack Requests

80C wrote:

Obviously I didn't put the fist code table I've posted here, because that's specifical for Wood with Wood's adresses.
The codes I used are in the second table.

i didnt mention anything about sawakitas code. read again

here are your problems

+    ld hl,C36B            ;Coord

fix your typo (its $c3b6)

SET_PAL_InfoScreen isnt a palette, its a function that sends sgb packets

SET_PAL_InfoScreen:
    ld hl,PAL_SET_Info
    ld de,ATTR_BLK_Info
    jp SendPALandATTR    ;$6165
SET_PAL_InfoScreen2:
    ld hl,PAL_SET_Info2
    ld de,ATTR_BLK_00
    jp SendPALandATTR    ;$6165
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
PAL_SET_Info2:
    SGBpack PAL_SET,1
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw 0,0,0
    db 0

if youre trying to ape code from someone else you should at least look at it

Offline

#10 2013-11-09 15:46:37

80C
Banned
Registered: 2013-03-16
Post 1,186/1,257

Re: Hack Requests

comet wrote:
80C wrote:

Obviously I didn't put the fist code table I've posted here, because that's specifical for Wood with Wood's adresses.
The codes I used are in the second table.

i didnt mention anything about sawakitas code. read again

here are your problems

+    ld hl,C36B            ;Coord

fix your typo (its $c3b6)

SET_PAL_InfoScreen isnt a palette, its a function that sends sgb packets

SET_PAL_InfoScreen:
    ld hl,PAL_SET_Info
    ld de,ATTR_BLK_Info
    jp SendPALandATTR    ;$6165
SET_PAL_InfoScreen2:
    ld hl,PAL_SET_Info2
    ld de,ATTR_BLK_00
    jp SendPALandATTR    ;$6165
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
PAL_SET_Info2:
    SGBpack PAL_SET,1
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw PAL_BLUEMON
    dw 0,0,0
    db 0

This explains why my attempt failed.

Comet wrote:

if youre trying to ape code from someone else you should at least look at it

I'm trying to ape nobody since Sawakita released the whole source for the purpouse of use it\develope it - otherwise he wouldn't have had released it.

And anyway, I know there's still someone that might think that my whole hack is a kind of rip off, but if they really think that that's the case they should at least look at it.


I left this forum.

Offline

#11 2013-11-09 16:30:47

Danny-E 33
Administrator
Registered: 2012-06-09
Post 675/1,119

Re: Hack Requests

80C wrote:
comet wrote:

if youre trying to ape code from someone else you should at least look at it

I'm trying to ape nobody since Sawakita released the whole source for the purpouse of use it\develope it - otherwise he wouldn't have had released it.

Your response completely avoided the point comet was trying to make.
His main point was not to accuse you of ripping off Sawakita's code or being unoriginal, like you tried to make it about.
His point is that if you're going to copy someone else's code, you at least have to understand it for yourself.

Offline

#12 2013-11-18 13:17:24

80C
Banned
Registered: 2013-03-16
Post 1,195/1,257

Re: Hack Requests

Danny-E 33 wrote:
80C wrote:
comet wrote:

if youre trying to ape code from someone else you should at least look at it

I'm trying to ape nobody since Sawakita released the whole source for the purpouse of use it\develope it - otherwise he wouldn't have had released it.

Your response completely avoided the point comet was trying to make.
His main point was not to accuse you of ripping off Sawakita's code or being unoriginal, like you tried to make it about.
His point is that if you're going to copy someone else's code, you at least have to understand it for yourself.

No problem man!
I was really stressed 'cause I just came out from a hard day of study and travelling (120km) 'cause of university!

@Comet
Yep, it seems I've mixed 2 bytes and confused the meaning of 3 lines but the rest seems to work.
Anyway I'm not sure I'll implement the extra screens for Demo2 cuz I've got to hurry and I've got some other urgent things to fix\add.

Okay, that's all for now!


I left this forum.

Offline

#13 2013-11-20 18:13:56

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 135/450
Website

Re: Hack Requests

Firstly, I'd like to thank you, Comet, for offering your time and effort to help other people when they are stuck.


This is my first attempt at ASM and I'm seeking for some advice. Any help would be greatly appreciated.

This is something I'd like to apply in a Pokemon Crystal hack I am working on at the moment.

My objective is to modify the obedience routine to expand it to one own's Pokemon instead of just affecting to traded Pokemon. I'd also like to make the disobeying chance more 'gradual' in relation to the level (explained below).

For example, in the game, the equivalent 'badge level' for having no badges is level 10. In that case, a traded level 10 Pokemon would disobey 0% of the time. A level 11 Pokemon would go on to disobey nearly 55% (11/21) of the time, and a level 12 Pokemon would disobey almost 60% (12/22) of the time. I'd like to remove the 'abruptness' of these percentages to give the player some margin of error so that a Pokemon doesn't turn into a nearly useless Pokemon as a result of being only one level above the 'permitted' level.

I plan on working on over the existing obedience routine of Pokemon Crystal, and I'm using the disassembly of Pokemon Crystal as a reference.

BattleCommand02: ; 343db
; checkobedience

; Enemy can't disobey
    ld a, [hBattleTurn]
    and a
    ret nz

    call Function0x34548
    ret nz

; If we've already checked this turn
    ld a, [AlreadyDisobeyed]
    and a
    ret nz

    xor a
    ld [AlreadyDisobeyed], a

; No obedience in link battles (since no handling exists for enemy)
    ld a, [InLinkBattle]
    and a
    ret nz

    ld a, [$cfc0]
    and a
    ret nz

; If the monster's id doesn't match the player's,
; some conditions need to be met.
    ld a, PartyMon1ID - PartyMon1
    call BattlePartyAttr

    ld a, [PlayerID]
    cp [hl]
    jr nz, .obeylevel
    inc hl
    ld a, [PlayerID + 1]
    cp [hl]
    ret z


.obeylevel


(...)

This is what I have thought of so far:

1. The first part would consist on ignoring whether the Pokemon has a different ID number or not (if it's traded or not), so that the obedience check is applied to every Pokemon.

The part that checks for whether the Pokemon is traded or not is:

; If the monster's id doesn't match the player's,
; some conditions need to be met.
ld a, PartyMon1ID - PartyMon1
    call BattlePartyAttr

    ld a, [PlayerID]
    cp [hl]
    jr nz, .obeylevel
    inc hl
    ld a, [PlayerID + 1]
    cp [hl]
    ret z

If I'm not mistaken this routine reaches the return if the ID of the Pokemon and the ID of the trainer coincides. If so, no obedience checks are applied. Otherwise, I think, it jumps to .obeylevel.

My idea was that, since I want it to end up in .obeylevel regardless, I could NOP that part considering that .obeylevel comes right after its end, meaning it would look like.

NOP
NOP
NOP
(...)

.obeylevel
; The maximum obedience level is constrained by owned badges:
    ld hl, JohtoBadges
(...)

If I got that part right, then the other thing I'd have to do is work on the obedience mechanics. I have considered multiple paths to take and after some time thinking about it, I decided that a not very difficult way to do it would be the one I'm going to detail here. I opted for it because it doesn't seem to require to get into the obedience formulas, but just working over the .obeylevel subroutine. In Pokemon Crystal this subroutine looks like this:

.obeylevel
; The maximum obedience level is constrained by owned badges:
    ld hl, JohtoBadges

; risingbadge
    bit 7, [hl]
    ld a, 101
    jr nz, .getlevel

; stormbadge
    bit 5, [hl]
    ld a, 70
    jr nz, .getlevel

; fogbadge
    bit 3, [hl]
    ld a, 50
    jr nz, .getlevel

; hivebadge
    bit 1, [hl]
    ld a, 30
    jr nz, .getlevel

; no badges
    ld a, 10

What I have thought about, is doing the following for each badge (in this example, considering that I wanted every Pokemon below level 84 to obey upon receiving the risingbadge):

; risingbadge
    bit 7, [hl]
    ld a, 84
.rand    
    call FarBattleRNG
    cp 4
    jr nc, .rand

    add  84 to result of rand

    jr nz, .getlevel

My idea is that a random number that can be either 0,1,2,3 or 4 is generated and it's added to the base level at which Pokemon always obey, which, in this case, is 84. If this code works the way I thought, there is a 20% chance that the Badge Level is 84, another 20% chance that the badge level is 85, and similarly up to level 88%. Ultimately, this would make the disobey chance of a level 85 Pokemon be around 10% (~50% · 1/5), the disobey chance of a level 86 Pokemon be slightly higher than 20%, and so on.

Modifying the .obeylevel subroutine that way, would require more space than there actually is. My idea was that I would turn the .obeylevel routine into:

Call [i]newroutine[/i]
NOP
NOP
NOP
(...)

and remake the routine and place it near the end of the bank (at ~0x37F00) where there is over 2Kb of space. That routine would end with a Return so that it returns to .obeylevel which would then go through the NOPs until the next subroutine .getlevel is reached. From there, everything else would be left untouched.


This is all I have in mind now. The first thing I am looking for is, if possible, confirmation on whether my general plan is correct or if there is something wrong. This way I'd be able to start working on it knowing that the result could be the desired one. If so, I would try to figure out by myself a way to use the Add command correctly to add the initial badge level and the result of the random number generator, which is, by now, what I don't know very well how to do it.

Many, many thanks in advance! :)

Last edited by Crystal_ (2013-11-20 18:15:50)

Offline

#14 2013-11-21 06:39:04

Miksy91
Member
Registered: 2010-10-16
Post 1,979/2,339

Re: Hack Requests

Sounds like you're going with a good mindset Crystal!
I'm not catching up with everything you've written there since some used routines don't say a thing (for example FarBattleRNG).

But anyway, the way I see it, you only need to focus on that "newroutine" which would set the percentage chance based on the pokemon level. You could for example do that with a loop so that you loop ([current level] - [required level]) this way;

obeying chance = 100%;
while (current level > required level) {
obeying chance - 10%;
current level - 1;
}

If you want to go for something more tricky which would apply for the situation better, like involving changes between "badge levels", why not go for it. But try to finish the code simply first and if it works, edit it to function better.

Last edited by Miksy91 (2013-11-21 06:41:00)

Offline

#15 2013-11-21 08:30:27

comet
Member
Registered: 2012-04-09
Post 315/679

Re: Hack Requests

Crystal_ wrote:

Firstly, I'd like to thank you, Comet, for offering your time and effort to help other people when they are stuck.

the idea with this thread was to do stuff for people who would otherwise give up on a project. if you guys needed help all this time you should have just asked!


Crystal_ wrote:

I opted for it because it doesn't seem to require to get into the obedience formulas, but just working over the .obeylevel subroutine.

for all that talk it sounds like you should just edit the formula

its really not too hard check it out

.getlevel
; c = obedience level
; d = monster level
; b = c + d

        ld b, a
        ld c, a

        ld a, [BattleMonLevel]
        ld d, a

        add b
        ld b, a

right now it weighs your monster's level against itself plus a baseline (10), so your distribution looks like this:

11/21 -> 52.4%
12/22 -> 54.5%
13/23 -> 56.5%
14/24 -> 58.3%
15/25 -> 60.0%
16/26 -> 61.5%
17/27 -> 63.0%
18/28 -> 64.3%
19/29 -> 65.5%

but if you subtracted the baseline instead:

1/11 -> 9.1%
2/12 -> 16.7%
3/13 -> 23.1%
4/14 -> 28.6%
5/15 -> 33.3%
6/16 -> 37.5%
7/17 -> 41.2%
8/18 -> 44.4%
9/19 -> 47.4%

Last edited by comet (2014-09-09 08:19:31)

Offline

#16 2013-11-21 11:08:28

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 136/450
Website

Re: Hack Requests

I'm not catching up with everything you've written there since some used routines don't say a thing (for example FarBattleRNG).

FarBattleRNG is often referenced in the dissasembly. If I'm right it just gets a random number between 0-255. (actually, now that I check the dissasembly, it looks like it's been renamed to BattleRandom)

but if you subtracted the baseline instead

1/11 -> 9.1%
2/12 -> 16.7%
3/13 -> 23.1%
4/14 -> 28.6%
5/15 -> 33.3%
6/16 -> 37.5%
7/17 -> 41.2%
8/18 -> 44.4%
9/19 -> 47.4%

I had considered doing something like that before, but, while it looks well for level 10, for badge levels (what you are calling baseline) higher than 10 (e.g. 80), the chances would look like 1/81, 2/82..., which are extremely small.

In the end I thought that working over the obeylevel routine would the the best thing since I plan on exapnding it to add more badges regardless.


EDIT: I have been working on the modifying obeylevel routine. However, there are many things I'm not sure about, and I'll also need help to code the routine in hex. I hope that everything is at least clearly commented:

http://pastebin.com/mpawbEjy

.obeylevel
; Effective badge level is Initial badge level + R, where R is
; a random number between 0 and 4, 20% chance each number
; All sixteen badges are considered

; KantoBadges
    ld hl, KantoBadges

; earthbadge
    bit 7, [hl]
    ld b, 101    ; Initial badge level. Using register b because 
            ; register a is used by FarBattleRNG
.rand0    
    call FarBattleRNG ; if i'm not mistaken, FarBattleRNG, now called 
              ; BattleRandom, returns a random number in register a
    swap a         ; this instruction is used everytime FarBattleRNG is called,
               ; but I'm not sure what it is for
    cp 4
    jr nc, .rand0    ; if it's not 0, 1, 2, 3, or 4, repeat
    add b            ; adds b and a in register a?
    jr nz, .getlevel    ; jumps to getlevel with register a = 
                ; Initial badge level + random number? 

; similar structure for the other badges
; volcanobadge
    bit 6, [hl]
    ld b, 98
.rand1    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand1
    add b
    jr nz, .getlevel

; marshbadge
    bit 5, [hl]
    ld b, 96
.rand2    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand2
    add b
    jr nz, .getlevel

; soulbadge
    bit 4, [hl]
    ld b, 94
.rand3    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand3
    add b
    jr nz, .getlevel

; rainbowbadge
    bit 3, [hl]
    ld b, 92
.rand4    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand4
    add b
    jr nz, .getlevel

; thunderbadge
    bit 2, [hl]
    ld b, 90
.rand5    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand5
    add b
    jr nz, .getlevel

; cascadebadge
    bit 1, [hl]
    ld b, 88
.rand6    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand6
    add b
    jr nz, .getlevel

; boulderbadge
    bit 0, [hl]
    ld b, 86
.rand7    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand7
    add b
    jr nz, .getlevel


; JohtoBadges
    ld hl, JohtoBadges

; risingbadge
    bit 7, [hl]
    ld b, 84
.rand8    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand8
    add b
    jr nz, .getlevel

; mineralbadge
    bit 4, [hl]
    ld b, 73
.rand9    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand9
    add b
    jr nz, .getlevel

; stormbadge
    bit 5, [hl]
    ld b, 63
.rand10    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand10
    add b
    jr nz, .getlevel

; glacierbadge
    bit 6, [hl]
    ld b, 60
.rand11    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand11
    add b
    jr nz, .getlevel

; fogbadge
    bit 3, [hl]
    ld b, 54
.rand12    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand12
    add b
    jr nz, .getlevel

; plainbadge
    bit 2, [hl]
    ld b, 45
.rand13    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand13
    add b
    jr nz, .getlevel

; hivebadge
    bit 1, [hl]
    ld b, 38
.rand14    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand14
    add b
    jr nz, .getlevel

; zephyrbadge
    bit 0, [hl]
    ld b, 30
.rand15    
    call FarBattleRNG
    swap a
    cp 4
    jr nc, .rand15
    add b
    jr nz, .getlevel

; no badges
    ld a, 20    ; register a = 20

Last edited by Crystal_ (2013-11-21 18:50:38)

Offline

#17 2013-11-21 22:02:53

comet
Member
Registered: 2012-04-09
Post 319/679

Re: Hack Requests

use a table instead. that way you also dont have to get each badge in order

.obeylevel

    ld hl, JohtoBadges
    ld b, 2
    call CountSetBits
    ld e, a
    ld d, 0

    ld hl, BadgeLevels
    add hl, de
    ld a, [hl]

    ld b, a
    call BattleRandom
    and 3
    add b

.getlevel

    ...


BadgeLevels:
    db 20 ; no badges
    db 30, 38, 45, 54, 60, 63, 73, 84
    db 86, 88, 90, 92, 94, 96, 98, 101

also

  • swap a swaps nybbles (4f -> f4). no real reason to have it

  • carry is set if a cp underflows (x - 4 < 0 so x < 4). so c is < and nc is >=

  • by the time you hit the jr nz, .getlevel in your example youve long since overwritten the result of bit x, [hl]

Offline

#18 2013-11-21 22:45:10

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 138/450
Website

Re: Hack Requests

Okay, let me see if I got it right.

- When CountSetBits is called it reads 8 bits starting from JohtoBadges twice, meaning it reads the bits from JohtoBadges and the bits from KantoBadges. The count of how many bits are set is loaded in register a.
- Number of bits set is loaded in registers de.
- The location of BadgeLevels is loaded in hl
- Then you do hl + de to get the wanted location in the table, and the value of the resulting location is loaded in a and b.
- The And 3 makes the random number gotten be equal or inferior to 3, and you add that number to b (badge level).

I don't imagine myself being able to come up with these kind of things. I took me ages just to understand it...

BTW, when I code ld hl, BadgeLevels, how should I translate 'BadgeLevels'? I guess it's some sort of two byte pointer to where the BadgeLevels table actually is, but is the pointer calculated similarly to the way pointers are calculated in scripts (big endian, to ram area of 0x4000 - 0x7fff)?
EDIT: nevermind, found out that the answer is yes.

Thanks for your help again!

Last edited by Crystal_ (2013-11-21 23:44:22)

Offline

#19 2013-11-22 00:22:03

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 139/450
Website

Re: Hack Requests

Double-posting just to let you know that I'm nearly 100% sure I got it to work (you can't never be too sure, I guess?). I've done multiple tests (nearly 200 attacks, not kidding :o) with different levels and different badge counts and I've always gotten accurate obeying percentages (or always obey if level<badge level), regardless of whether the pokemon is traded or not as well. So it seems that everything is working perfectly.

I would like to thank you once again for all the help (or I should say, for doing all the work :P) and also because of the fact that I was able to more or less understand what you did, which may help me in the future.

Last edited by Crystal_ (2013-11-22 00:23:49)

Offline

#20 2013-11-30 15:42:11

triumph
Member
Registered: 2013-11-14
Post 4/66

Re: Hack Requests

Do you know how I can edit the base stats of Missingno. (B8) in hex editing? (Pokémon Red)
I just found the base stats in Pokédex order.
Because B8 with the Extender Tool has Tackle and Tail Whip, and no backsprite, and I don't know where I can find him. I also don't know where is his frontsprite/and his dimentions of his frontsprite located.

Offline

#21 2013-12-03 20:17:28

ShaneM
Member
From: United States (USA)
Registered: 2013-03-11
Post 257/287
Website

Re: Hack Requests

triumph wrote:

Do you know how I can edit the base stats of Missingno. (B8) in hex editing? (Pokémon Red)
I just found the base stats in Pokédex order.
Because B8 with the Extender Tool has Tackle and Tail Whip, and no backsprite, and I don't know where I can find him. I also don't know where is his frontsprite/and his dimentions of his frontsprite located.

Originally, Missingno. shared a Biker's data. With the Pokemon Extender, his base stats got moved to 0xFDBE4. Base stats data are 0x1c (28) bytes long. If you want to add a sprite for him, you can. It even has its own dex entry. Currently, at 0xFDBE4, there are 28 $00's. So, the game will crash if you try to catch a Missingno, using a Gameshark. Just assign it base stats as a normal Pokemon, since it no longer shares the Biker's data.

NOTE: In my Green version, I made Missingno. a real Pokemon with a real sprite. You can do the same, too. Give it a 0x66 for sprite size, though, to fix the Hall of Fame glitch.

Btw, $B8 is not a regular Missingno. It is said that there are 39 Missingno.s, but there are in fact 36. ($B6-B8 are the constants for Fossil and Ghost sprites; in Green Japan, they aren't even called Missingno. for those three, but "FOSSIL" and "GHOST". Dunno why the English Red/Blue changed it.) $B8 shares the base stats and Type/Attack data of the last Pokemon viewed. There are no fixed moves for it, unless you change the routine in bank0.

If you have any more questions regarding Missingno., or need help. Visit my forum.

Last edited by ShaneM (2013-12-03 20:30:14)


I'm back. I'll try not to get as frustrated with stupid questions. People on my naughty list:

*Pokemon_Master
*Noizy
*lipun
*Spambots

Offline

#22 2014-02-21 17:33:08

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 166/450
Website

Re: Hack Requests

Comet, are you still taking requests? This thread is quite old, so I'd like to be sure before I make the post explaining the request. I don't want to make you feel 'forced' to do something you don't want to.

Offline

#23 2014-02-21 23:51:57

comet
Member
Registered: 2012-04-09
Post 366/679

Re: Hack Requests

don't ask to ask

Offline

#24 2014-02-22 20:40:32

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 167/450
Website

Re: Hack Requests

Okay then.

Actually, rather than doing something it's more about searching something for me.

It's the formula of the bug catching contest in the national park. As much as I try, it keeps eluding me. I've gotten more familiar with debugging and asm in recent months and I've been able to do things with them on my own, but still no luck with this one.

Basically, when the bug catching contest ends, you are given a score based on some of the attributes of the pokemon you catch (as long as you catch a pokemon; if you catch two or more, you are forced to pick only one). The score is weighted against three(?) scores that are, as far as I know, calculated more or less? randomly (usually around 300-350 points). You are given a different prize depending on whether you finish first, second, or third, or otherwise given the consolation prize.

During the contest helper's speech after the contest has ended, part of the text consists of saying something like "X, who caught Pokemon Y, finished in position N with a score of M points" three times, for 1st, 2nd and 3rd scores. These three scores correspond to the player and two other participants, or to three participants if you didn't finish 3rd or above. These scores are read two ram addresses each. However, it's not as easy as applying a minor hack to edit these addresses (e.g. add 200 points to all except yours) in the moment they are loaded into ram, because before this happens, it has already been calculated the position in which each participant finishes and, of course, the prizes given to everybody.

So, you know, I got to find the formula that calculates the points you are given, to modify it. But everything I could come up with and  tried, I failed. Debugging on access to the ram addresses are loaded always ends up into some generic routine that copies chunks of data and I couldn't manage to track the process backwards. I also even tried to debug when ram addresses like current hp is accessed on read, since the formula uses for example the hp remaining when the pokemon was caught. I also tried putting breakpoints on the divide/multiply routines but no luck either. I tried other things that I don't remember at the moment... I don't even have any clue about whether the formula is calculated right after the pokemon is caught, in the exact moment the contest ends, or during the speech. As you can see, I'm completely lost!

Anyway, this is the formula in case it helps:

(Maximum HP * 4) + Attack + Defense + Speed + Sp.Attack + Sp.Defense + A + int(Current HP/8)+B

A is based on the diversification values (DVs, individual values) of the caught Pokémon:
A starts with 0.
If half the Defense DV, rounded down, is odd, add 16 to A.
If half the Attack DV, rounded down, is odd, add 8 to A.
If half the Special DV, rounded down, is odd, add 4 to A.
If half the Speed DV, rounded down, is odd, add 1 to A.
If the Pokémon is holding an item, B is 1; otherwise B is 0.
The game truncates each stat (including total and current HP) to the lowest 8 bits for the purposes of this formula.

Thanks in advance. (PS sorry for the wall of text, just wanted to give you as much info as I could!)

Offline

#25 2014-02-22 22:04:39

AtecainCorp.
Member
Registered: 2013-04-14
Post 617/627

Re: Hack Requests

I give you challenge. Can you port DENJUU from KEITAI DENJUU TELEFANG to Pokemon Gold and set limiter to 172 kinds of monsters?


http://hax.iimarck.us/topic/3435/ - Pokemon Ruby GEN V GRAPHIC hack Thread
http://hax.iimarck.us/topic/3476/ - Unused Music Midi Thread
http://hax.iimarck.us/topic/3579/ - Some info about region Thonsu

Offline

Board footer

Powered by FluxBB