Skip to content

Commit 7a8bc4a

Browse files
SonoSooSISSOtm
andauthored
The big cycle unit rework (#534)
* Fix ambiguity in clock units The M-cycle crusade! * Fix missing terminator * Fix typos and missed spelling errors * Correct and convert "Timer Global Circuit" to SVG Fixes #492 by moving the DIV-APU bits from 5 and 6 to 4 and 5. Also applies the "TODO: correct the diagram" note. Also tries to reorganise the diagram and reword some bits to be more consistent with the rest of the document, and improve clarity. * Correctly reflect which bits don't exist on the diagram * Provide fallback values for viewing the SVG stand-alone * Convert DIV+TAC diagrams to "themed" SVGs Also restore the CGB version of that diagram * Tweak presentation of "system counter" a little --------- Co-authored-by: Eldred HABERT <[email protected]>
1 parent 2810432 commit 7a8bc4a

19 files changed

+347
-4228
lines changed

src/CGB_Registers.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ would be recommended to use Single Speed whenever possible.
168168

169169
In Double Speed Mode the following will operate twice as fast as normal:
170170

171-
- The CPU (2.10 MHz, so 1 cycle = approx. 0.5 µs)
171+
- The CPU (2.10 MHz, so 1 M-cycle = approx. 0.5 µs)
172172
- Timer and Divider Registers
173173
- Serial Port (Link Cable)
174174
- DMA Transfer to OAM
@@ -179,7 +179,7 @@ And the following will keep operating as usual:
179179
- HDMA Transfer to VRAM
180180
- All Sound Timings and Frequencies
181181

182-
The CPU stops for 2050 cycles (= 8200 clocks) after the `stop` instruction is
182+
The CPU stops for 2050 M-cycles (= 8200 T-cycles) after the `stop` instruction is
183183
executed. During this time, the CPU is in a strange state. `DIV` does not tick, so
184184
*some* audio events are not processed. Additionally, VRAM/OAM/... locking is "frozen", yielding
185185
different results depending on the [PPU mode](<#PPU modes>) it's started in:

src/Gameboy_Camera.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ This means that the GB Camera shouldn't be used in GBC double speed mode!
187187
:::
188188

189189
The time needed to capture and process an image depends on the exposure time and the value of N bit of the register 1 of the M64282FP chip.
190-
In GAME BOY CYCLES (1 MiHz):
190+
In Game Boy M-cycles (1 MiHz):
191191

192192
```
193193
N_bit = ([A001] & BIT(7)) ? 0 : 512
@@ -200,7 +200,7 @@ Divide those values by 2 to get the sensor clocks.
200200
### Capture process timings
201201

202202
The next values are in sensor clocks.
203-
Multiply by 2 to get Game Boy cycles:
203+
Multiply by 2 to get Game Boy M-cycles:
204204

205205
```
206206
- Reset pulse.

src/MBC3.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,4 @@ Year-10000-Proof, provided that the cartridge gets used at least every
9393
### Delays
9494

9595
When accessing the RTC Registers, it is recommended to wait 4 µs
96-
(4 cycles in Normal Speed Mode) between any separate accesses.
96+
(4 M-cycles in Single Speed Mode) between any separate accesses.

src/MBC5.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ It can map up to 64 Mbits (8 MiB) of ROM.
55
MBC5 (Memory Bank Controller 5) is the 4th generation MBC. There
66
apparently was no MBC4, presumably because of the superstition about the
77
number 4 in Japanese culture. It is the first MBC that is guaranteed to
8-
work properly with GBC double speed mode.
8+
work properly with GBC Double Speed mode.
99

1010
## Memory
1111

src/OAM_Corruption_Bug.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ The following operations are affected by this bug:
4747
- `push rr`, the `call` family, `rst xx` and interrupt handling -
4848
Pushing to the stack will trigger the bug 4 times; two usual writes
4949
and two glitched writes caused by the implied `dec sp`. However, since one
50-
glitched write occurs in the same cycle as a actual write, this will
50+
glitched write occurs in the same M-cycle as a actual write, this will
5151
effectively behave like 3 writes.
5252
- Executing code from OAM - If PC is inside OAM (reading $FF,
5353
that is, `rst $38`) the bug will trigger twice, once for increasing PC

src/OAM_DMA_Transfer.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Source: $XX00-$XX9F ;XX = $00 to $DF
1212
Destination: $FE00-$FE9F
1313
```
1414

15-
The transfer takes 160 machine cycles: 640 dots (1.4 lines) in normal speed,
15+
The transfer takes 160 M-cycles: 640 dots (1.4 lines) in normal speed,
1616
or 320 dots (0.7 lines) in CGB Double Speed Mode.
1717
This is much faster than a CPU-driven copy.
1818

@@ -64,15 +64,15 @@ Many games copy a routine like it into HRAM and call it during Mode 1.
6464
run_dma:
6565
ld a, HIGH(start address)
6666
ldh [$FF46], a ; start DMA transfer (starts right after instruction)
67-
ld a, 40 ; delay for a total of 4×40 = 160 cycles
67+
ld a, 40 ; delay for a total of 4×40 = 160 M-cycles
6868
.wait
69-
dec a ; 1 cycle
70-
jr nz, .wait ; 3 cycles
69+
dec a ; 1 M-cycle
70+
jr nz, .wait ; 3 M-cycles
7171
ret
7272
```
7373

7474
If HRAM is tight, this more compact procedure saves 5 bytes of HRAM
75-
at the cost of a few cycles spent jumping to the tail in HRAM.
75+
at the cost of a few M-cycles spent jumping to the tail in HRAM.
7676

7777
```rgbasm
7878
run_dma: ; This part must be in ROM.
@@ -86,8 +86,8 @@ run_dma_tail: ; This part must be in HRAM.
8686
.wait
8787
dec b
8888
jr nz, .wait
89-
ret z ; Conditional `ret` is 1 cycle slower, which avoids
90-
; reading from the stack on the last cycle of DMA.
89+
ret z ; Conditional `ret` is 1 M-cycle slower, which avoids
90+
; reading from the stack on the last M-cycle of DMA.
9191
```
9292

9393
If starting a mid-frame transfer, wait for Mode 0 first

src/Rendering.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The main implication of this rendering process is the existence of **raster effe
99
The most famous raster effect is modifying the [scrolling registers](<#LCD Position and Scrolling>) between scanlines to create a ["wavy" effect](https://gbdev.io/guides/deadcscroll#effects).
1010

1111
A "**dot**" = one 2<sup>22</sup> Hz (≅ 4.194 MHz) time unit.
12-
Dots remain the same regardless of whether the CPU is in [double speed](<#FF4D — KEY1 (CGB Mode only): Prepare speed switch>), so there are 4 dots per single-speed CPU cycle, and 2 per double-speed CPU cycle.
12+
Dots remain the same regardless of whether the CPU is in [Double Speed mode](<#FF4D — KEY1 (CGB Mode only): Prepare speed switch>), so there are 4 dots per Single Speed M-cycle, and 2 per Double Speed M-cycle.
1313

1414
:::tip NOTE
1515

@@ -64,10 +64,10 @@ Only the OBJ's leftmost pixel matters here, transparent or not; it is designated
6464
3. Incur this many dots of penalty, or zero if negative (from waiting for the BG fetch to finish).
6565
3. Incur a flat, 6-dot penalty (from fetching the OBJ's tile).
6666

67-
**Exception**: an OBJ with an OAM X position of 0 (thus, completely off the left side of the screen) always incurs a 11-cycle penalty, regardless of `SCX`.
67+
**Exception**: an OBJ with an OAM X position of 0 (thus, completely off the left side of the screen) always incurs a 11-dot penalty, regardless of `SCX`.
6868

6969

70-
[^first12]: The 12 extra cycles come from two tile fetches at the beginning of Mode 3. One is the first tile in the scanline (the one that gets shifted by `SCX` % 8 pixels), the other is simply discarded.
70+
[^first12]: The 12 extra dots of penalty come from two tile fetches at the beginning of Mode 3. One is the first tile in the scanline (the one that gets shifted by `SCX` % 8 pixels), the other is simply discarded.
7171

7272
[^crt]: The Game Boy can afford to "take pauses", because it writes to a LCD it fully controls; by contrast, home consoles like the NES or SNES are on a schedule imposed by the screen they are hooked up to. Taking pauses arguably simplified the PPU's design while allowing greater flexibility to game developers.
7373

src/STAT.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
:::tip TERMINOLOGY
44

5-
A *dot* is the shortest period over which the PPU can output one pixel: is it equivalent to 1 T-state on DMG or on CGB single-speed mode or 2 T-states on CGB double-speed mode. On each dot during mode 3, either the PPU outputs a pixel or the fetcher is stalling the [FIFOs](<#Pixel FIFO>).
5+
A *dot* is the shortest period over which the PPU can output one pixel: is it equivalent to 1 T-cycle on DMG or on CGB Single Speed mode or 2 T-cycles on CGB Double Speed mode. On each dot during mode 3, either the PPU outputs a pixel or the fetcher is stalling the [FIFOs](<#Pixel FIFO>).
66

77
:::
88

@@ -36,7 +36,7 @@ is set, and (if enabled) a STAT interrupt is requested.
3636
A hardware quirk in the monochrome Game Boy makes the LCD interrupt
3737
sometimes trigger when writing to STAT (including writing \$00) during
3838
OAM scan, HBlank, VBlank, or LY=LYC. It behaves as if \$FF were
39-
written for one cycle, and then the written value were written the next
40-
cycle. Because the GBC in DMG mode does not have this quirk, two games
39+
written for one M-cycle, and then the written value were written the next
40+
M-cycle. Because the GBC in DMG mode does not have this quirk, two games
4141
that depend on this quirk (Ocean's *Road Rash* and Vic Tokai's *Xerd
4242
no Densetsu*) will not run on a GBC.

src/Timer_Obscure_Behaviour.md

+42-21
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,63 @@
11
# Timer obscure behaviour
22

3+
:::tip System counter
4+
5+
DIV is just the visible part of the **system counter**.
6+
7+
The **system counter** is constantly incrementing every M-cycle, unless the CPU is in [STOP mode](<#Using the STOP Instruction>).
8+
9+
:::
10+
311
## Timer Global Circuit
412

5-
![](imgs/timer_simplified.svg "imgs/timer_simplified.svg")
13+
{{#include imgs/src/timer_simplified.svg:2:}}
614

715
## Relation between Timer and Divider register
816

917
This is a schematic of the circuit involving TAC and DIV:
1018

11-
![](imgs/timer_tac_bug_dmg.svg "imgs/timer_tac_bug_dmg.svg")
19+
<figure><figcaption>
20+
21+
On **DMG**:
22+
23+
</figcaption>
24+
{{#include imgs/src/timer_tac_bug_dmg.svg:2:}}
25+
</figure>
26+
27+
<figure><figcaption>
28+
29+
On **CGB**:
30+
31+
</figcaption>
32+
{{#include imgs/src/timer_tac_bug_gbc.svg:2:}}
33+
</figure>
1234

1335
Notice how the values that are connected to the inputs of the
1436
multiplexer are the values of those bits, not the carry of those bits.
1537
This is the reason of a few things:
1638

17-
- When writing to DIV, the whole counter is reset, so the timer is
39+
- When writing to DIV, the system counter is reset to zero, so the timer is
1840
also affected.
1941

2042
- When writing to DIV, if the current output is 1 and timer is
21-
enabled, as the new value after reseting DIV will be 0, the falling
43+
enabled, as the new value after reseting the system counter will be 0, the falling
2244
edge detector will detect a falling edge and TIMA will increase.
2345

2446
- When writing to TAC, if the previously selected multiplexer input was
25-
1 and the new input is 0, TIMA will increase too. This doesnt
47+
1 and the new input is 0, TIMA will increase too. This doesn't
2648
happen when the timer is disabled, but it also happens when disabling
27-
the timer (the same effect as writing to DIV). The following code explains the behaviour in DMG and MGB.
49+
the timer (the same effect as writing to DIV). The following code explains the behavior in DMG and MGB.
2850

2951
```
30-
clocks_array[4] = {1024, 16, 64, 256}
52+
clocks_array[4] = {256, 4, 16, 64}
3153
3254
old_clocks = clocks_array[old_TAC&3]
3355
new_clocks = clocks_array[new_TAC&3]
3456
3557
old_enable = old_TAC & BIT(2)
3658
new_enable = new_TAC & BIT(2)
3759
38-
sys_clocks = 16 bit system counter
60+
sys_clocks = system counter
3961
4062
IF old_enable == 0 THEN
4163
glitch = 0 (*)
@@ -50,24 +72,23 @@ the timer (the same effect as writing to DIV). The following code explains the b
5072

5173
The sentence marked with a (\*) has a different behaviour in GBC (AGB
5274
and AGS seem to have strange behaviour even in the other statements).
53-
When enabling the timer and maintaining the same frequency it doesnt
54-
glitch. When disabling the timer it doesnt glitch either. When another
75+
When enabling the timer and maintaining the same frequency it doesn't
76+
glitch. When disabling the timer it doesn't glitch either. When another
5577
change of value happens (so timer is enabled after the write), the
5678
behaviour depends on a race condition, so it cannot be predicted for
5779
every device.
5880

5981
## Timer Overflow Behaviour
6082

6183
When TIMA overflows, the value from TMA is loaded and IF timer flag is
62-
set to 1, but this doesnt happen immediately. Timer interrupt is
63-
delayed 1 cycle (4 clocks) from the TIMA overflow. The TMA reload to
64-
TIMA is also delayed. For one cycle, after overflowing TIMA, the value
84+
set to 1, but this doesn't happen immediately. Timer interrupt is
85+
delayed 1 M-cycle from the TIMA overflow. The TMA reload to
86+
TIMA is also delayed. For 1 M-cycle, after overflowing TIMA, the value
6587
in TIMA is $00, not TMA. This happens only when an overflow happens, not
66-
when the upper bit goes from 1 to 0, it cant be done manually writing
88+
when the upper bit goes from 1 to 0, it can't be done manually writing
6789
to TIMA, the timer has to increment itself.
6890

69-
For example (SYS is the system internal counter divided by 4 for easier
70-
understanding, each increment of the graph is 1 cycle, not 1 clock):
91+
For example (SYS here is the lower 8 bits of the system counter):
7192

7293
Timer overflows:
7394

@@ -88,14 +109,14 @@ understanding, each increment of the graph is 1 cycle, not 1 clock):
88109
- During the strange cycle \[A\] you can prevent the IF flag from being
89110
set and prevent the TIMA from being reloaded from TMA by writing a value
90111
to TIMA. That new value will be the one that stays in the TIMA register
91-
after the instruction. Writing to DIV, TAC or other registers wont
112+
after the instruction. Writing to DIV, TAC or other registers won't
92113
prevent the IF flag from being set or TIMA from being reloaded.
93114

94-
- If you write to TIMA during the cycle that TMA is being loaded to it
115+
- If you write to TIMA during the M-cycle that TMA is being loaded to it
95116
\[B\], the write will be ignored and TMA value will be written to TIMA
96117
instead.
97118

98-
- If TMA is written the same cycle it is loaded to TIMA \[B\], TIMA is
119+
- If TMA is written the same M-cycle it is loaded to TIMA \[B\], TIMA is
99120
also loaded with that value.
100121

101122
- This is a guessed schematic to explain the priorities with registers
@@ -105,5 +126,5 @@ TIMA and TMA:
105126

106127
TMA is a latch. As soon as it is written, the output shows that value.
107128
That explains that when TMA is written and TIMA is being incremented,
108-
the value written to TMA is also written to TIMA. It doesnt affect the
109-
IF flag, though.
129+
the value written to TMA is also written to TIMA. It doesn't affect the
130+
IF flag though.

src/Timer_and_Divider_Registers.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ TAC (because every increment is an overflow). However, if TMA is set to $FE, an
3636
only requested every two increments, which effectively divides the selected clock by two. Setting
3737
TMA to $FD would divide the clock by three, and so on.
3838

39-
If a TMA write is executed on the same cycle as the content of TMA is transferred to TIMA
39+
If a TMA write is executed on the same M-cycle as the content of TMA is transferred to TIMA
4040
due to a timer overflow, the old value is transferred to TIMA.
4141

4242
## FF07 — TAC: Timer control
@@ -51,13 +51,13 @@ due to a timer overflow, the old value is transferred to TIMA.
5151

5252
<div class="table-wrapper"><table>
5353
<thead>
54-
<tr><th rowspan=2>Clock select</th><th rowspan=2>Base clock</th><th colspan=3>Frequency (Hz)</th></tr>
54+
<tr><th rowspan=2>Clock select</th><th rowspan=2>Increment every</th><th colspan=3>Frequency (Hz)</th></tr>
5555
<tr><th>DMG, SGB2, CGB in single-speed mode</th><th>SGB1</th><th>CGB in double-speed mode</th></tr>
5656
</thead><tbody>
57-
<tr><td>00</td><td>CPU Clock / 1024</td><td> 4096</td><td> ~4194</td><td> 8192</td></tr>
58-
<tr><td>01</td><td>CPU Clock / 16 </td><td>262144</td><td>~268400</td><td>524288</td></tr>
59-
<tr><td>10</td><td>CPU Clock / 64 </td><td> 65536</td><td> ~67110</td><td>131072</td></tr>
60-
<tr><td>11</td><td>CPU Clock / 256 </td><td> 16384</td><td> ~16780</td><td> 32768</td></tr>
57+
<tr><td>00</td><td>256 M-cycles </td><td> 4096</td><td> ~4194</td><td> 8192</td></tr>
58+
<tr><td>01</td><td>4 M-cycles </td><td>262144</td><td>~268400</td><td>524288</td></tr>
59+
<tr><td>10</td><td>16 M-cycles </td><td> 65536</td><td> ~67110</td><td>131072</td></tr>
60+
<tr><td>11</td><td>64 M-cycles </td><td> 16384</td><td> ~16780</td><td> 32768</td></tr>
6161
</tbody>
6262
</table></div>
6363

0 commit comments

Comments
 (0)