+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  [BGB] How to break on "A Button Pressed" event?
Pages: [1]
Author Topic: [BGB] How to break on "A Button Pressed" event?  (Read 1 times)
ubitux
Guest
« on: March 10, 2010, 11:55:53 am »

Hi,

As the title says, I'm trying to break on the "A Button Pressed" event under BGB. According to the GB CPU Manual, page 35-36, it seems I have to catch events when the GB reads at 0xFF00. But if do that, BGB break every single time I try to play, which is logical since the game tries to catch any event the whole time.

As it's the only way I know, I tried to simulate the A key press event by putting 10 in "a" register (after a break), but it does not seem to follow the process I hope (the game played as if nothing happened).

Also, I did not understood well the GB Manual:

First, page 36, first line of code, we can read "LA A,$20 <- bit 5 = $20", but for me 0x20 = 0b100000 which sounds like the bit 6 for me.
Secondly, the next instruction with its comment: "LD ($FF00),A <- select P14 by setting it low". Why P14? According to the page 35, bit 5 is P15 out port, and bit 6 is "Not used".

So I'm lost with all this stuff...

Can anyone help?

Thanks
Tauwasser
Guest
« Reply #1 on: March 10, 2010, 12:35:18 pm »

Quote from: ubitux on March 10, 2010, 11:55:53 am
0x20 = 0b100000 which sounds like the bit 6 for me.
Bits are usually numbered from lowest to highest significance. It's basically place-value notation, so the least significant bit is bit 0, not bit 1. That will clear that up.

Quote from: ubitux on March 10, 2010, 11:55:53 am
Why P14?
The code gets direction keys first, then gets button presses after that. Remember, the pin that is selected is the one that is LOW (0). The return values (bits 3 to 0) will be LOW (0) for pressed buttons and HIGH (1) for released buttons.

The example code is incorrect, here's the real deal:

Code:
       Example code:

          Game: Ms. Pacman
          Address: $3b1

        LD A,$20       <- bit 5 = $20
        LD ($FF00),A   <- select P14 by setting it low
        LD A,($FF00)
        LD A,($FF00)   <- wait a few cycles
        CPL            <- complement A
        AND $0F        <- get only first 4 bits
        SWAP A         <- swap it
        LD B,A         <- store A in B
        LD A,$10
        LD ($FF00),A   <- select P15 by setting it low
        LD A,($FF00)
        LD A,($FF00)
        LD A,($FF00)
        LD A,($FF00)
        LD A,($FF00)
        LD A,($FF00)   <- Wait a few MORE cycles
        CPL            <- complement (invert)
        AND $0F        <- get first 4 bits
        OR B           <- put A and B together

        LD D,A         <- store A in D
        LD A,($FF8B)   <- read old joy data from ram
        XOR D          <- toggle w/current button bit
        AND D          <- get current button bit back
        LD ($FF8C),A   <- save in new Joydata storage
        LD A,D         <- put original value in A
        LD ($FF8B),A   <- store it as old joy data


        LD A,$30       <- deselect P14 and P15
        LD ($FF00),A   <- RESET Joypad
        RET            <- Return from Subroutine

          The button values using the above method are such:
          $8 - Start             $80 - Down
          $4 - Select            $40 - Up
          $2 - B                 $20 - Left
          $1 - A                 $10 - Right

          Let's say we held down A, Start, and Up.
          The value returned in accumulator A would be $49

Back to your original question.

Quote from: ubitux on March 10, 2010, 11:55:53 am
As it's the only way I know, I tried to simulate the A key press event by putting 10 in "a" register (after a break)

This should work, however, the game might be making sure that it doesn't read noise. That's why Ms. Pac-Man has the value read from the run before stored at $FF8B. It makes sure that it doesn't act on button presses that lasted less than the reading interval of one execution of the button routine, that way filtering out noise (though I do not know how common it is to actually get false positives for the joypad).
Thus, you should use a conditional breakpoint in BGB. To do that, go to Debug --> Breakpoints. Point PC where you want it, the last read of joypad data for P15, and put in as condition A=$01 if your data is complemented (CPL) and the first four bits are cut off (AND A, $0F). If the game doesn't do that for you, you will have to set the condition to A=$DE for the same effect. Mind you, this will only get button presses of A that are standalone (no B, Start, Select pressed at the same time).

I hope this clears things up for you.

cYa,

Tauwasser
ubitux
Guest
« Reply #2 on: March 11, 2010, 03:26:05 pm »

Oh, thanks a thousand times, you'd help me a lot!

Well, I've managed to do what I wanted, here is the path I took and how I understood it, please correct me if I say something wrong:

In BGB, I started using the access breakpoints feature to monitor any access to the I/O address 0xff00.

The debugger broke immediately on a code very similar to the one in Ms. Pacman: they first wrote 0x20 (0b00100000 -> 0b..10....) at 0xff00 which mean they select the P14 pin (zero value on bit 4) in order to watch for arrows input. The code is then followed by reading during a few cycles if there is any input.

Next was the part I was interested in; they wrote 0x10 (0b00010000 -> 0b..01....) at 0xff00 which mean they select the P15 pin (zero value on bit 5). As I pressed nothing (no time for it before the break),  the value read in "a" register was 0xDF (0b11011111)

According to the manual, we have this:

Code:
0b11011111
  ^^^^^^^^
  ||||````-- Last four bits: respectively Start, Select, B and A, which are all "Up" (set to "1")
  |||`------ Bit 4 to one -> Pin 14 -> do not read for arrows
  ||`------- Bit 5 to zero -> Pin 15 -> read buttons
  ``-------- Two unused bit

As I want to simulate a "Button A pressed" event, I just need to change the last bit which means to put 0b11011110 (0xDE) in register "a"; I just did it before the CPL instruction were executed, and it worked :crazy:

So, really, thanks a lot to you (and another friend who help me to understand all this stuff) Smiley
Pages: [1]  


Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC