blob: 5501465699769f35a7047b25c708af3dc8cf6fc2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
<?php
namespace GameBoy;
class LcdController
{
protected $core;
public function __construct($core)
{
$this->core = $core;
}
/**
* Scan Line and STAT Mode Control
* @param int $line Memory Scanline
*/
public function scanLine($line)
{
//When turned off = Do nothing!
//@TODO - Move LCDisOn to this class
if ($this->core->LCDisOn) {
if ($line < 143) {
//We're on a normal scan line:
if ($this->core->LCDTicks < 20) {
$this->core->scanLineMode2(); // mode2: 80 cycles
} elseif ($this->core->LCDTicks < 63) {
$this->core->scanLineMode3(); // mode3: 172 cycles
} elseif ($this->core->LCDTicks < 114) {
$this->core->scanLineMode0(); // mode0: 204 cycles
} else {
//We're on a new scan line:
$this->core->LCDTicks -= 114;
$this->core->actualScanLine = ++$this->core->memory[0xFF44];
$this->core->matchLYC();
if ($this->core->STATTracker != 2) {
if ($this->core->hdmaRunning && !$this->core->halt && $this->core->LCDisOn) {
$this->core->performHdma(); //H-Blank DMA
}
if ($this->core->mode0TriggerSTAT) {
$this->core->memory[0xFF0F] |= 0x2; // set IF bit 1
}
}
$this->core->STATTracker = 0;
$this->core->scanLineMode2(); // mode2: 80 cycles
if ($this->core->LCDTicks >= 114) {
//We need to skip 1 or more scan lines:
$this->core->notifyScanline();
$this->scanLine($this->core->actualScanLine); //Scan Line and STAT Mode Control
}
}
} elseif ($line == 143) {
//We're on the last visible scan line of the LCD screen:
if ($this->core->LCDTicks < 20) {
$this->core->scanLineMode2(); // mode2: 80 cycles
} elseif ($this->core->LCDTicks < 63) {
$this->core->scanLineMode3(); // mode3: 172 cycles
} elseif ($this->core->LCDTicks < 114) {
$this->core->scanLineMode0(); // mode0: 204 cycles
} else {
//Starting V-Blank:
//Just finished the last visible scan line:
$this->core->LCDTicks -= 114;
$this->core->actualScanLine = ++$this->core->memory[0xFF44];
$this->core->matchLYC();
if ($this->core->mode1TriggerSTAT) {
$this->core->memory[0xFF0F] |= 0x2; // set IF bit 1
}
if ($this->core->STATTracker != 2) {
if ($this->core->hdmaRunning && !$this->core->halt && $this->core->LCDisOn) {
$this->core->performHdma(); //H-Blank DMA
}
if ($this->core->mode0TriggerSTAT) {
$this->core->memory[0xFF0F] |= 0x2; // set IF bit 1
}
}
$this->core->STATTracker = 0;
$this->core->modeSTAT = 1;
$this->core->memory[0xFF0F] |= 0x1; // set IF flag 0
//LCD off takes at least 2 frames.
if ($this->core->drewBlank > 0) {
--$this->core->drewBlank;
}
if ($this->core->LCDTicks >= 114) {
//We need to skip 1 or more scan lines:
$this->scanLine($this->core->actualScanLine); //Scan Line and STAT Mode Control
}
}
} elseif ($line < 153) {
//In VBlank
if ($this->core->LCDTicks >= 114) {
//We're on a new scan line:
$this->core->LCDTicks -= 114;
$this->core->actualScanLine = ++$this->core->memory[0xFF44];
$this->core->matchLYC();
if ($this->core->LCDTicks >= 114) {
//We need to skip 1 or more scan lines:
$this->scanLine($this->core->actualScanLine); //Scan Line and STAT Mode Control
}
}
} else {
//VBlank Ending (We're on the last actual scan line)
if ($this->core->memory[0xFF44] == 153) {
$this->core->memory[0xFF44] = 0; //LY register resets to 0 early.
$this->core->matchLYC(); //LY==LYC Test is early here (Fixes specific one-line glitches (example: Kirby2 intro)).
}
if ($this->core->LCDTicks >= 114) {
//We reset back to the beginning:
$this->core->LCDTicks -= 114;
$this->core->actualScanLine = 0;
$this->core->scanLineMode2(); // mode2: 80 cycles
if ($this->core->LCDTicks >= 114) {
//We need to skip 1 or more scan lines:
$this->scanLine($this->core->actualScanLine); //Scan Line and STAT Mode Control
}
}
}
}
}
}
|