Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2012-11-24 17:19:04

Miksy91
Member
Registered: 2010-10-16
Post 1,273/2,311

ID number in the beginning

If you set a breakpoint to 01:5C41 and click "NEW GAME" from the menu, you can start debugging the routine used for choosing ID number.

01:5C41
ld hl, C300
ld bc, 0E99
xor a
call 314C
ld hl, D1A1
ld bc, 0D60
xor a
call 314C
ld a, (FF44)
ld (FF00 + E5), a
call 032E
ld a, (FFE4)
ld (D1A1), a
ld a, (FF44)
ld (FFE5), a
call 032E
ld a, (FFE3)
ld (D1A2), a
...

00:314C
inc b
inc c
jr @3151 (--> dec c)
ldi (hl), a
dec c
jr nz, 3150 (--> ldi (hl), a)
dec b
jr nz, 3150
ret

00:032E
ld a, 01
ld (CEEA), a
halt
nop
ld a, (CEEA)
and a
jr nz, 0333 (--> halt)
ret

I was debugging the routine before, didn't clearly understand the purpose of those two subroutines but seemingly they have something to do with ram ram FF00 + XX. After the first call to 314C, hl is set to D199 yet it's hard to tell what's the purpose of this routine incrementing hl from C300 to D199 either.

Calls to 032E define the value written to FFE4 or FFE3 one way or another (related to halt and nop instructions probably).

Anyway, I was thinking of using this routine for drawing a random byte value and storing it somewhere in ram for a script of mine which requires that. Would it be completely okay to use this routine as a base? It doesn't seem to affect unwanted parts of ram any way at all so I think I'd be good to go with it. Felt like asking your opinion about it though (comet, Tauwasser, IIMarckus, kbm, Sawakita, ..., someone who knows this stuff better than I do).

Last edited by Miksy91 (2012-11-24 17:20:03)

Offline

#2 2012-11-24 19:46:47

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

Re: ID number in the beginning

I guess this is either Gold, Silver or Crystal, right?

Routine 0x32e is basically identical to the routine used in RBY for waiting for a VBlank interrupt to occur ("halt" instruction reduces power consumpution during the wait). It allows the screen to be refreshed/updated.

Routine 0x314c reminds me C's memset function: it writes a's value into the memory area beginning at [hl] and ending at [hl + bc] (that's why right after it's called the first time you get 0xD199 = 0xC300 + 0x0E99). I wouldn't use routine 01:5C41 during game because it basically sets to 0 all the RAM areas that will store the game progress (such as bag content, money, possibly event flags, etc.).

It seems that random numbers are generated by reading LY register (mapped at RAM:FF44) in two different times. It seems weird, so I might be wrong.

In RBY there's a routine that reads random values from 0xFF04 (DI register). Red's routine is located at 04:7A8F, is usually called using the shortcut routine 0x3E5C, and is documented in my scripting notes under «GET_RND_NUM», if you're interested.

Last edited by Sawakita (2012-11-24 20:08:41)

Offline

#3 2012-11-24 20:16:43

comet
Member
Registered: 2012-04-09
Post 36/675

Re: ID number in the beginning

GSC's is identical to Red's. Note that Crystal's RNG result is at $ffe1-2; Gold's is at $ffe3-4.

The callable RNG is at Gold:30a2 (Crystal:2f8c):

RNG: ; 2f8c
; generate a random word
; output:
;    a: lo
;    ffe1: hi
;    ffe2: lo
    push bc

; get divider
    ld a, [$ff00+$4] ; divider
    ld b, a

; add to hi
    ld a, [$ff00+$e1]
    adc b
    ld [$ff00+$e1], a

; get divider
    ld a, [$ff00+$4] ; divider
    ld b, a

; sub from lo
    ld a, [$ff00+$e2]
    sbc b
    ld [$ff00+$e2], a

    pop bc
    ret
; 2f9f

From nocash:

FF04 - DIV - Divider Register (R/W)
This register is incremented at rate of 16384Hz (~16779Hz on SGB). In CGB Double Speed Mode it is incremented twice as fast, ie. at 32768Hz. Writing any value to this register resets it to 00h.

There is also an RNG built into the game loop (starts at $2b5 in Crystal). Since this is already done on a per-frame basis the RNG is actually called pretty infrequently. Link battles use a separate PRNG to avoid desync.

Offline

#4 2012-11-25 08:33:02

Miksy91
Member
Registered: 2010-10-16
Post 1,274/2,311

Re: ID number in the beginning

Sawakita wrote:

Routine 0x314c reminds me C's memset function: it writes a's value into the memory area beginning at [hl] and ending at [hl + bc] (that's why right after it's called the first time you get 0xD199 = 0xC300 + 0x0E99). I wouldn't use routine 01:5C41 during game because it basically sets to 0 all the RAM areas that will store the game progress (such as bag content, money, possibly event flags, etc.).

I wasn't planning to use this routine straight as its own. Only parts of it, unaffecting ram area between hl and hl + bc. If that routine (00:314C) does have a reason for being there for FF44, I could switch ldi (hl), a with inc hl, perhaps?

Sawakita wrote:

It seems that random numbers are generated by reading LY register (mapped at RAM:FF44) in two different times. It seems weird, so I might be wrong.

In RBY there's a routine that reads random values from 0xFF04 (DI register). Red's routine is located at 04:7A8F, is usually called using the shortcut routine 0x3E5C, and is documented in my scripting notes under «GET_RND_NUM», if you're interested.

Sounds like following that path will turn out a much better way of doing it, thanks!


comet wrote:

GSC's is identical to Red's. Note that Crystal's RNG result is at $ffe1-2; Gold's is at $ffe3-4.

The callable RNG is at Gold:30a2 (Crystal:2f8c):

RNG: ; 2f8c
; generate a random word
; output:
;    a: lo
;    ffe1: hi
;    ffe2: lo
    push bc

; get divider
    ld a, [$ff00+$4] ; divider
    ld b, a

; add to hi
    ld a, [$ff00+$e1]
    adc b
    ld [$ff00+$e1], a

; get divider
    ld a, [$ff00+$4] ; divider
    ld b, a

; sub from lo
    ld a, [$ff00+$e2]
    sbc b
    ld [$ff00+$e2], a

    pop bc
    ret
; 2f9f

From nocash:

FF04 - DIV - Divider Register (R/W)
This register is incremented at rate of 16384Hz (~16779Hz on SGB). In CGB Double Speed Mode it is incremented twice as fast, ie. at 32768Hz. Writing any value to this register resets it to 00h.

There is also an RNG built into the game loop (starts at $2b5 in Crystal). Since this is already done on a per-frame basis the RNG is actually called pretty infrequently. Link battles use a separate PRNG to avoid desync.

Is there any reason why you named FFE3-FFE4 high and low RNG result?

Also, what I don't understand here is why the generated word in FFE3-FFE4 (in G/S) is totally random. It looks like both FFE3 and FFE4 are only 2x "carry flag" away from each other or is the rate 16384/s (Hz) really that high compared how the processor is executing code that they won't really match up in any way? Either way, it should suit this case just fine anyway because I won't be needing both the values.

Besides, any ideas why carry flag is related to the process?


Thanks for the info though, it totally helped!

Offline

#5 2012-11-25 21:17:19

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

Re: ID number in the beginning

Miksy91 wrote:

I wasn't planning to use this routine straight as its own. Only parts of it, unaffecting ram area between hl and hl + bc. If that routine (00:314C) does have a reason for being there for FF44, I could switch ldi (hl), a with inc hl, perhaps?

When you say «planning to use...parts of it» you mean "rewrite somewhere else in a different way", right?  I hope you don't mean you'll modify it in place. Also, 0xFF44 (register LY) and routine 0x314C aren't related each other. What did you mean, there? Replacing «ldi [hl],a» with «inc hl» in routine 0x314C would make it useless.

Comet showed that there's a RNG routine, like in RBY, in GSC too; the code you posted doesn't contain the random number generating code.

Offline

#6 2012-11-25 21:28:05

Miksy91
Member
Registered: 2010-10-16
Post 1,278/2,311

Re: ID number in the beginning

Sawakita wrote:

When you say «planning to use...parts of it» you mean "rewrite somewhere else in a different way", right?  I hope you don't mean you'll modify it in place. Also, 0xFF44 (register LY) and routine 0x314C aren't related each other. What did you mean, there? Replacing «ldi [hl],a» with «inc hl» in routine 0x314C would make it useless.

No, of course I wouldn't modify an existing code, not in rom bank 0.
I would have created a new code similar to that.

If register LY and 0x314C had some relation to one another (like value in LY depending on a loop or something? I dunno. It wouldn't make any sense for them to have such relation. Just like you said here, there is not.), I could have made it so hl would still be incremented in the same way without loading anything to addresses of hl.

Sawakita wrote:

Comet showed that there's a RNG routine, like in RBY, in GSC too; the code you posted doesn't contain the random number generating code.

During this process, random numbers are still drawn into D1A1 and D1A2.

Offline

#7 2012-11-25 21:58:02

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

Re: ID number in the beginning

Miksy91 wrote:

If register LY and 0x314C had some relation to one another (like value in LY depending on a loop or something? I dunno. It wouldn't make any sense for them to have such relation. Just like you said here, there is not.), I could have made it so hl would still be incremented in the same way without loading anything to addresses of hl.

«The LY indicates the vertical line to which the present data is transferred to the LCD Driver» (cit. pandocs).

Miksy91 wrote:

During this process, random numbers are still drawn into D1A1 and D1A2.

In fact that's what made me suppose that in GSC random values for the player's ID aren't created by reading values produced by the DIV register (0xFF04), but instead by using the LY register's value (which is quite faster than the DIV, although CPU clock is faster of both anyway by about 2-3 orders of magnitude).

Random numbers, in my understanding, are generated thanks to the use of a "seed" (implemented by either adding/subtracting the new value to it), rather than because of a different frequency of clocks. In fact (again, if I'm not wrong) the new values used to generate high and low byte of the new random number are almost alway the same (because DIV updates itself more slowly than the CPU processes instructions); what makes a real difference is the fact that the value is one time added and one time subtracted.

Offline

Board footer

Powered by FluxBB