Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix times signs #490

Merged
merged 2 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/CPU_Registers_and_Flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Is set in these cases:
- When the result of an 8-bit addition is higher than $FF.
- When the result of a 16-bit addition is higher than $FFFF.
- When the result of a subtraction or comparison
is lower than zero (like in Z80 and 80x86 CPUs, but unlike in
is lower than zero (like in Z80 and x86 CPUs, but unlike in
65XX and ARM CPUs).
- When a rotate/shift operation shifts out a \"1\" bit.

Expand Down
34 changes: 17 additions & 17 deletions src/Four_Player_Adapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ run 1/4 as fast as the clock used for normal serial transfers on the DMG

Byte | Value | Description
-----|-------|-------------
1 | 0xFE | ID Byte
2 | 0x?? | STAT1
3 | 0x?? | STAT2
4 | 0x?? | STAT3
1 | \$FE | ID Byte
2 | ?? | STAT1
3 | ?? | STAT2
4 | ?? | STAT3

3 "STAT" bytes are sent indicating the current connection status of the other
Game Boys. Each byte is usually the same, however, sometimes the status can
Expand All @@ -57,20 +57,20 @@ the DMG-07. In this way, the Game Boy broadcasts across the Link Cable network
that it is an active participant in communications. It also acts as a sort of
acknowledgement signal, where software can drop a Game Boy if the DMG-07
detects an improper response during a ping, or a Game Boy simply quits the
network. The proper response is to send 0x88 *after* receiving the ID Byte and
network. The proper response is to send \$88 *after* receiving the ID Byte and
STAT1, in which case the upper-half of STAT1, STAT2, and STAT3 are updated to
show that a Game Boy is "connected". If for whatever reason, the
acknowledgement codes are not sent, the above bits are unset.

Some examples of ping packets are shown below:

Packet | Description
----------------------|-------------------------------------------------------
`0xFE 0x01 0x01 0x01` | Ping packet received by Player 1 with no other Game Boys connected.
`0xFE 0x11 0x11 0x11` | Ping packet received by Player 1 when Player 1 has connected.
`0xFE 0x31 0x31 0x31` | Ping packet received by Player 1 when Players 1 & 2 have connected.
`0xFE 0x71 0x71 0x71` | Ping packet received by Player 1 when Players 1, 2, & 3 have connected.
`0xFE 0x62 0x62 0x62` | Ping packet received by Player 2 when Players 2 & 3 are connected (but not Player 1).
Packet | Description
--------------|-------------------------------------------------------
`FE 01 01 01` | Ping packet received by Player 1 with no other Game Boys connected.
`FE 11 11 11` | Ping packet received by Player 1 when Player 1 has connected.
`FE 31 31 31` | Ping packet received by Player 1 when Players 1 & 2 have connected.
`FE 71 71 71` | Ping packet received by Player 1 when Players 1, 2, & 3 have connected.
`FE 62 62 62` | Ping packet received by Player 2 when Players 2 & 3 are connected (but not Player 1).

It's possible to have situations where some players are connected but others
are not; the gaps don't matter. For example, Player 1 and Player 4 can be
Expand All @@ -92,8 +92,8 @@ should respond to all bytes in a ping packet:
----------------------------
DMG-07 Game Boy
----------------------------
0xFE <--> (ACK1) = 0x88
STAT1 <--> (ACK2) = 0x88
\$FE <--> (ACK1) = \$88
STAT1 <--> (ACK2) = \$88
STAT2 <--> (RATE) = Link Cable Speed
STAT3 <--> (SIZE) = Packet Size
```
Expand All @@ -107,7 +107,7 @@ DMG-07 Bits-Per-Second --> 4194304 / ((6 * RATE) + 512)
```

The lowest setting (RATE = 0) runs the DMG-07 at the normal speed DMGs usually
transfer data (1KB/s), while setting it to 0xFF runs it close to the slowest
transfer data (1KB/s), while setting it to \$FF runs it close to the slowest
speed (2042 bits-per-second).

SIZE sets the length of packets exchanged between all Game Boys. Nothing fancy,
Expand All @@ -116,7 +116,7 @@ just the number of bytes in each packet. It probably shouldn't be set to zero.
### Transmission Phase

When the master Game Boy (Player 1) is ready, it should send 4 bytes
(`0xAA 0xAA 0xAA 0xAA`, if those are actually required should be investigated further).
(`AA AA AA AA`, if those are actually required should be investigated further).
This alerts the DMG-07 to start the transmission phase. The RATE and SIZE parameters
are applied at this point. The protocol is simple: Each Game Boy sends a packet to
the DMG-07 simultaneously, then the DMG-07 outputs each packet to all connected
Expand Down Expand Up @@ -190,7 +190,7 @@ buffer.

It's possible to restart the ping phase while operating in the transmission
phase. To do so, the master Game Boy should send 4 or more bytes
(`0xFF 0xFF 0xFF 0xFF`, it's possible fewer 0xFF bytes need to be sent,
(`FF FF FF FF`, it's possible fewer \$FF bytes need to be sent,
but this has not been extensively investigated yet). The bytes alert the DMG-07
that the ping phase should begin again, after which it sends ping packets after
a brief delay. During this delay, the transmission protocol is still working as
Expand Down
8 changes: 4 additions & 4 deletions src/Gameboy_Camera.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ Multiply by 2 to get Game Boy cycles:

```
- Reset pulse.
- Configure sensor registers. (11 x 8 CLKs)
- Configure sensor registers. (11 × 8 CLKs)
- Wait (1 CLK)
- Start pulse (1 CLK)
- Exposure time (exposure_steps x 8 CLKs)
- Exposure time (exposure_steps × 8 CLKs)
- Wait (2 CLKs)
- Read start
- Read period (N=1 ? 16128 : 16384 CLKs)
Expand All @@ -224,7 +224,7 @@ Above is the previous result divided by 2.
During the read process, every pixel is written when it is read from the sensor.
If the read process is stopped, (by shutting the GB off, for example) the RAM will have contents of the current picture until the read was stopped.
From there, it will have the data from the image captured before that one.
The sensor transfers are 128x128 pixels, but the upper and lower rows are corrupted.
The sensor transfers are 128×128 pixels, but the upper and lower rows are corrupted.
The Game Boy Camera controller uses the medium rows of the sensor image.
This means that it ignores the first 8 rows and the last 8 rows.

Expand Down Expand Up @@ -288,7 +288,7 @@ However, if N = "1", `exposure_steps` should be greater than or equal to $0030.

```
u16 exposure_steps ((Reg2)<<8) | [Reg3]
Step time = 1 / 1048576 Hz * 16 = 0,954 µs* 16 = 15,259 µs
Step time = 1 / 1048576 Hz * 16 = 0,954 µs * 16 = 15,259 µs
```

It's a bit less than the 16 µs the datasheet says, but it's close enough.
Expand Down
6 changes: 3 additions & 3 deletions src/Gameboy_Printer.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ $280 bytes, multiple \"command 4 packets\" have to be sent.

The graphics are organized in the normal tile format (16 bytes per
tile), and the tiles are sent in the same order they occur on your
tilemap (do keep in mind though that the printer does \*not\* have 32x32
tiles space for a map, but only 20x18).
tilemap (do keep in mind though that the printer does \*not\* have 32×32
tiles space for a map, but only 20×18).

An empty data packet must be sent before sending command 2 to print the
data, otherwise the print command will be ignored.
Expand Down Expand Up @@ -122,7 +122,7 @@ Bit \# | Name | Description
packet. It's best to send a packet completely or with very little
delay between the individual bytes, otherwise the packet may not be
accepted.**
- To print things larger than 20x18 (like GB Camera images with big
- To print things larger than 20×18 (like GB Camera images with big
borders), multiple data packets with a following print command need
to be sent. The print command should be set to no linefeed (neither
before nor after) to allow for continuous printing.
Expand Down
14 changes: 7 additions & 7 deletions src/IR.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ While a number of games may use similar formats for their IR communications, the

Again, there is no set or established infrared protocol that games must follow. Many games vary in their approach. For example, the 2nd Generation Pokemon games use the GBC's hardware timers, while others have hardcoded values that count cycles to check timing. The simplest form is a bare-bones communication protocol, i.e. something like a binary Morse code where a "0" is a long ON-OFF pulse and "1" is a short ON-OFF pulse or vice versa. Properly done, data could have been short, compact, and easily converted into bytes in RAM. Sakura Taisen GB seems to follow this model in its communications with the Pocket Sakura. Not all games do this, however, and appear to be doing who knows that, opting instead for customized and specialized communications unique to each title. To illustrate this idea, it would be possible to use a table of given lengths of IR ON-OFF pulses so that individual bytes could be sent all at once instead of in a binary, bit-by-bit manner. A number of games try to send a few pulses when pressing input like the A button and wait for another GBC to echo that in response, but after the handshake, most of the IR pulses are impossible to understand without disassembling the code.

One thing to note is that 4 games in particular do share somewhat similar IR protocols, at least regarding the initial handshake between 2 GBCs. They are Pokemon TCG 1 & 2 and Bombermax Red & Blue, all from the "2-Player Init" category above. Typically, IR capable GBC games will continually wait for an IR signal on both sides, i.e. the "1-Player Init" category. When one player presses certain input, that GBC takes the initiative and sends out a few IR pulses. That is to say, for most IR games, it only takes *just one* player to start the entire process.
One thing to note is that 4 games in particular do share somewhat similar IR protocols, at least regarding the initial handshake between 2 GBCs. They are Pokemon TCG 1 & 2 and Bomberman Max Red & Blue, all from the "2-Player Init" category above. Typically, IR capable GBC games will continually wait for an IR signal on both sides, i.e. the "1-Player Init" category. When one player presses certain input, that GBC takes the initiative and sends out a few IR pulses. That is to say, for most IR games, it only takes *just one* player to start the entire process.

The handshake for the 4 games previously mentioned, however, requires *both* players to input at almost the same time. One has to be slightly faster or slower than the other. Each side continually sends a few IR pulses, then reads the sensor to see if anything was received. If so, the GBCs begin to sync. The idea is that one side should be sending while the other is checking, and then the handshake completes. This is why one side needs to be faster or slower to input; if they are sending IR signals at the same time, they don't see anything when reading the sensor. As a result, both GBCs cannot input at exactly the same time. Practically speaking, this is unlikely to happen under normal circumstances, since most humans can't synchronize their actions down to a handful of microseconds, so the handshake will normally succeed.

## RP Register

The following is just theory. This handshake is possibly an artifact of the HuC-1. Consider that the Japanese version of Pokemon TCG 1 used the HuC-1 for its IR communications, and the developers may have borrowed the "best practices" used by other HuC-1/"GB KISS" games. When bringing Pokemon TCG 1 overseas, the IR handling code was likely minimally adapted to use the GBC's IR port, with the underlying protocol remaining unchanged in most regards. Pokemon TCG 2 ditched the HuC-1 in favor of the GBC IR port, so the IR code from non-Japanese versions of Pokemon TCG 1 was copy+pasted. The Bomberman games were made by Hudson Soft, literally the same people who created the HuC-1 in the first place. They too probably used the same protocol that had worked forever in their "GB KISS" games, so they used the same handshake method as before, just on the GBC IR port now. More research into the HuC-1 itself and the games needs to be done to confirm any of this.

On the GBC, the MMIO register located at 0xFF56 controls infrared communication. Simply known as "RP" (Radiation Port? Reception Port? Red Port???), it is responsible for sending and receiving IR signals. Below is a diagram of the 8-bit register:
On the GBC, the MMIO register located at \$FF56 controls infrared communication. Simply known as "RP" (Radiation Port? Reception Port? Red Port???), it is responsible for sending and receiving IR signals. Below is a diagram of the 8-bit register:

| Bit(s) | Effect | Access |
|--------|-----------------------------------------------|--------|
Expand All @@ -38,7 +38,7 @@ On the GBC, the MMIO register located at 0xFF56 controls infrared communication.
| 2-5 | Unused | |
| 6-7 | Signal Read Enable (0 = Disable) (3 = Enable) | R/W |

Turning on the IR light is as simple as writing to Bit 0 of RP. Reading is a bit more complicated. Bits 6 and 7 must both be set (0xC0), to read Bit 1, otherwise Bit 1 returns 1, acting as if no signal is detected, except in edge cases detailed below in "Obscure Behavior". With signal reading enabled, Bit 1 will determine the status of any incoming IR signals. Like other Game Boy MMIO registers, unused bits read high (set to 1).
Turning on the IR light is as simple as writing to Bit 0 of RP. Reading is a bit more complicated. Bits 6 and 7 must both be set (\$C0), to read Bit 1, otherwise Bit 1 returns 1, acting as if no signal is detected, except in edge cases detailed below in "Obscure Behavior". With signal reading enabled, Bit 1 will determine the status of any incoming IR signals. Like other Game Boy MMIO registers, unused bits read high (set to 1).

## Signal Fade

Expand All @@ -52,14 +52,14 @@ At about 3.0 to 3.5 inches (7.62 to 8.89 cm) signal fade time appears to be arou

The RP register has one very strange quirk. Disabling Bits 6 and 7 and then subsequently re-enabling them causes Bit 1 to go to zero under certain conditions. In other words, the IR sensor will act as if it is detecting a signal if reading the signal is disabled then enabled. It seems this behavior happens in the presence of any light; covering up the sensor during the read signal disable/enable causes the sensor to act normally. It's possible that the sensor resets itself (to its lowest level of detection???) and immediately detects any infrared sources, even from ambient/environmental light. The presence of any noise may temporarily trick the sensor into "seeing" IR light. By abusing this behavior, the GBC has some rudimentary ability to gauge the type of nearby lighting:

| Result of 1st RP Write (0x00) | Result of 2nd RP Write (0xC0) | Type of Lighting |
| Result of 1st RP Write (\$00) | Result of 2nd RP Write (\$C0) | Type of Lighting |
|-------------------------------|-------------------------------|------------------|
| Bit 1 = 1 | Bit 1 = 1 | Dark |
| Bit 1 = 0 | Bit 1 = 1 | Ambient |
| Bit 1 = 0 (sometimes 1) | Bit 1 = 0 | Bright |

Writing 0x00 to RP, followed by 0xC0 will trigger these results listed above. One very important thing to note is that when enabling Bits 6 and 7 (writing 0xC0), it does take some time for the sensor to register legitimate IR light coming into the sensor. I.e. if you want to use this method to detect what kind of light a GBC is looking at, the software needs to loop for a bit until Bit 1 of RP changes. Generally a few hundred cycles in double-speed mode will suffice. If Bit 1 of RP remains 1 after the loop, it's safe to assume the lighting is either ambient or dark. This delay doesn't seem to happen when Bits 6 and 7 are never disabled (which is what most official GBC software does). Games typically write either 0xC0 or 0xC1 to RP, with a small handful setting it to 0x00 initially when setting up other MMIO registers (Pokemon G/S/C does this).
Writing \$00 to RP, followed by \$C0 will trigger these results listed above. One very important thing to note is that when enabling Bits 6 and 7 (writing \$C0), it does take some time for the sensor to register legitimate IR light coming into the sensor. I.e. if you want to use this method to detect what kind of light a GBC is looking at, the software needs to loop for a bit until Bit 1 of RP changes. Generally a few hundred cycles in double-speed mode will suffice. If Bit 1 of RP remains 1 after the loop, it's safe to assume the lighting is either ambient or dark. This delay doesn't seem to happen when Bits 6 and 7 are never disabled (which is what most official GBC software does). Games typically write either \$C0 or \$C1 to RP, with a small handful setting it to \$00 initially when setting up other MMIO registers (Pokemon G/S/C does this).

The downside to this method is that when detecting a bright IR source, the sensor quickly adjusts to this new level, and the next attempt at writing 0x00 followed by 0xC0 to RP will result in readings of dark or ambient (typically dark though). Essentially the bright result only appears briefly when transitioning from lower levels of light, then it "disappears" thanks to the short time it takes for IR signal fade. Designing a game mechanic (darkness and light) around this quirk is still possible, although it would require careful thought and planning to properly work around the observed limitations.
The downside to this method is that when detecting a bright IR source, the sensor quickly adjusts to this new level, and the next attempt at writing \$00 followed by \$C0 to RP will result in readings of dark or ambient (typically dark though). Essentially the bright result only appears briefly when transitioning from lower levels of light, then it "disappears" thanks to the short time it takes for IR signal fade. Designing a game mechanic (darkness and light) around this quirk is still possible, although it would require careful thought and planning to properly work around the observed limitations.

One suggested method: once the Bright setting is detected, switch to writing only 0xC0 to RP so that the IR sensor works normally. If IR light stops being detected, switch to alternating 0x00 and 0xC0 writes as described above to determine Dark or Ambient settings. Whether it's practical or not to do this in a game remains theoretical at this point.
One suggested method: once the Bright setting is detected, switch to writing only \$C0 to RP so that the IR sensor works normally. If IR light stops being detected, switch to alternating \$00 and \$C0 writes as described above to determine Dark or Ambient settings. Whether it's practical or not to do this in a game remains theoretical at this point.
2 changes: 1 addition & 1 deletion src/Joypad_Input.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## FF00 — P1/JOYP: Joypad

The eight Game Boy action/direction buttons are arranged as a 2x4
The eight Game Boy action/direction buttons are arranged as a 2×4
matrix. Select either action or direction buttons by writing to this
register, then read out the bits 0-3.

Expand Down
2 changes: 1 addition & 1 deletion src/MBC2.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MBC2

(max 256 KiB ROM and 512x4 bits RAM)
(max 256 KiB ROM and 512×4 bits RAM)

## Memory

Expand Down
Loading