Skip to content

Commit 6f7d940

Browse files
committed
Improved rendering
1 parent d13706b commit 6f7d940

File tree

11 files changed

+629
-139
lines changed

11 files changed

+629
-139
lines changed
56.3 KB
Binary file not shown.

resources/font/VT323-Regular.ttf

146 KB
Binary file not shown.

src/Application.php

Lines changed: 61 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
namespace App;
44

5+
use App\Renderer\GuiRenderer;
56
use App\Renderer\MonitorRenderer;
7+
use App\Renderer\RenderState;
68
use Error;
9+
use GL\Math\Vec2;
710
use GL\VectorGraphics\{VGAlign, VGColor, VGContext};
811

9-
use VISU\Graphics\{RenderTarget, Texture, TextureOptions};
12+
use VISU\Graphics\{RenderTarget, Texture, TextureOptions, Viewport};
1013
use VISU\Graphics\Rendering\Pass\ClearPass;
1114
use VISU\Graphics\Rendering\RenderContext;
1215
use VISU\Graphics\Rendering\Resource\RenderTargetResource;
@@ -23,8 +26,12 @@ class Application extends QuickstartApp
2326

2427
private bool $isRunning = false;
2528

29+
private RenderState $renderState;
30+
2631
private MonitorRenderer $monitorRenderer;
2732

33+
private GuiRenderer $guiRenderer;
34+
2835
/**
2936
* A function that is invoked once the app is ready to run.
3037
* This happens exactly just before the game loop starts.
@@ -47,9 +54,13 @@ public function ready() : void
4754

4855
$this->inputContext->registerAndActivate('main', $actions);
4956

50-
// load the inconsolata font to display the current score
51-
if ($this->vg->createFont('inconsolata', VISU_PATH_FRAMEWORK_RESOURCES_FONT . '/inconsolata/Inconsolata-Regular.ttf') === -1) {
52-
throw new Error('Inconsolata font could not be loaded.');
57+
// load the VT323 font
58+
if ($this->vg->createFont('vt323', VISU_PATH_RESOURCES . '/font/VT323-Regular.ttf') === -1) {
59+
throw new Error('vt323 font could not be loaded.');
60+
}
61+
62+
if ($this->vg->createFont('bebas', VISU_PATH_RESOURCES . '/font/BebasNeue-Regular.ttf') === -1) {
63+
throw new Error('Bebas font could not be loaded.');
5364
}
5465

5566
// create the chip8
@@ -73,9 +84,15 @@ public function ready() : void
7384

7485
// create a texture for the monitor
7586
$this->monitorTexture = new Texture($this->gl, 'chip8_monitor');
87+
88+
// rendering state
89+
$this->renderState = new RenderState;
7690

7791
// create a renderer for the monitor
78-
$this->monitorRenderer = new MonitorRenderer($this->gl);
92+
$this->monitorRenderer = new MonitorRenderer($this->gl, $this->renderState);
93+
94+
// create a renderer for the GUI
95+
$this->guiRenderer = new GuiRenderer($this->vg, $this->renderState, $this->input);
7996
}
8097
/**
8198
* Prepare / setup additional render passes before the quickstart draw pass
@@ -88,6 +105,19 @@ public function ready() : void
88105
*/
89106
public function setupDrawBefore(RenderContext $context, RenderTargetResource $renderTarget) : void
90107
{
108+
// we construct a viewport that matches the render target
109+
// this is not what we would usally use this helper for but in this case
110+
// its just a nice helper to work with our screen real estate
111+
$this->renderState->viewport = new Viewport(
112+
0,
113+
$renderTarget->width / $renderTarget->contentScaleX,
114+
$renderTarget->height / $renderTarget->contentScaleY,
115+
0,
116+
1.0,
117+
1.0
118+
119+
);
120+
91121
// upload the buffer
92122
$options = new TextureOptions();
93123
$options->dataFormat = GL_RED_INTEGER;
@@ -117,8 +147,11 @@ public function draw(RenderContext $context, RenderTarget $renderTarget) : void
117147

118148
$currentInst = $this->chip8->programCounter;
119149

150+
// draw the screen frame
151+
$this->guiRenderer->renderGUI($this->chip8);
152+
120153
// draw the current opcode
121-
$this->vg->fontFace('inconsolata');
154+
$this->vg->fontFace('vt323');
122155
$this->vg->fontSize(16);
123156
$this->vg->fillColor(VGColor::white());
124157
$this->vg->textAlign(VGAlign::LEFT | VGAlign::TOP);
@@ -169,7 +202,7 @@ public function update() : void
169202

170203
// toggle fullscreen
171204
if ($this->inputContext->actions->didButtonPress('fullscreen')) {
172-
$this->monitorRenderer->fullscreen = !$this->monitorRenderer->fullscreen;
205+
$this->renderState->fullscreenMonitor = !$this->renderState->fullscreenMonitor;
173206
}
174207

175208
// toggle crt effect
@@ -183,29 +216,32 @@ public function update() : void
183216
}
184217

185218
// update the keyboard states
186-
$this->chip8->keyPressStates[0x1] = (int) $this->input->isKeyPressed(Key::NUM_1);
187-
$this->chip8->keyPressStates[0x2] = (int) $this->input->isKeyPressed(Key::NUM_2);
188-
$this->chip8->keyPressStates[0x3] = (int) $this->input->isKeyPressed(Key::NUM_3);
189-
$this->chip8->keyPressStates[0xC] = (int) $this->input->isKeyPressed(Key::NUM_4);
190-
$this->chip8->keyPressStates[0x4] = (int) $this->input->isKeyPressed(Key::Q);
191-
$this->chip8->keyPressStates[0x5] = (int) $this->input->isKeyPressed(Key::W);
192-
$this->chip8->keyPressStates[0x6] = (int) $this->input->isKeyPressed(Key::E);
193-
$this->chip8->keyPressStates[0xD] = (int) $this->input->isKeyPressed(Key::R);
194-
$this->chip8->keyPressStates[0x7] = (int) $this->input->isKeyPressed(Key::A);
195-
$this->chip8->keyPressStates[0x8] = (int) $this->input->isKeyPressed(Key::S);
196-
$this->chip8->keyPressStates[0x9] = (int) $this->input->isKeyPressed(Key::D);
197-
$this->chip8->keyPressStates[0xE] = (int) $this->input->isKeyPressed(Key::F);
198-
$this->chip8->keyPressStates[0xA] = (int) $this->input->isKeyPressed(Key::Y);
199-
$this->chip8->keyPressStates[0x0] = (int) $this->input->isKeyPressed(Key::X);
200-
$this->chip8->keyPressStates[0xB] = (int) $this->input->isKeyPressed(Key::C);
201-
$this->chip8->keyPressStates[0xF] = (int) $this->input->isKeyPressed(Key::V);
202-
219+
if ($this->chip8->wantKeyboardUpdates) {
220+
$this->chip8->keyPressStates[0x1] = (int) $this->input->isKeyPressed(Key::NUM_1);
221+
$this->chip8->keyPressStates[0x2] = (int) $this->input->isKeyPressed(Key::NUM_2);
222+
$this->chip8->keyPressStates[0x3] = (int) $this->input->isKeyPressed(Key::NUM_3);
223+
$this->chip8->keyPressStates[0xC] = (int) $this->input->isKeyPressed(Key::NUM_4);
224+
$this->chip8->keyPressStates[0x4] = (int) $this->input->isKeyPressed(Key::Q);
225+
$this->chip8->keyPressStates[0x5] = (int) $this->input->isKeyPressed(Key::W);
226+
$this->chip8->keyPressStates[0x6] = (int) $this->input->isKeyPressed(Key::E);
227+
$this->chip8->keyPressStates[0xD] = (int) $this->input->isKeyPressed(Key::R);
228+
$this->chip8->keyPressStates[0x7] = (int) $this->input->isKeyPressed(Key::A);
229+
$this->chip8->keyPressStates[0x8] = (int) $this->input->isKeyPressed(Key::S);
230+
$this->chip8->keyPressStates[0x9] = (int) $this->input->isKeyPressed(Key::D);
231+
$this->chip8->keyPressStates[0xE] = (int) $this->input->isKeyPressed(Key::F);
232+
$this->chip8->keyPressStates[0xA] = (int) $this->input->isKeyPressed(Key::Y);
233+
$this->chip8->keyPressStates[0x0] = (int) $this->input->isKeyPressed(Key::X);
234+
$this->chip8->keyPressStates[0xB] = (int) $this->input->isKeyPressed(Key::C);
235+
$this->chip8->keyPressStates[0xF] = (int) $this->input->isKeyPressed(Key::V);
236+
}
203237

204238
if (!$this->isRunning) {
205239
return;
206240
}
207241

208242
$this->chip8->updateTimers();
209-
$this->chip8->runCycles(8);
243+
if ($this->chip8->runCycles(8) === 0) {
244+
$this->isRunning = false;
245+
}
210246
}
211247
}

src/CPU.php

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
*/
1515
class CPU
1616
{
17-
public UByteBuffer $registersV;
17+
public bool $shouldExit = false;
1818

19-
public int $registerI = 0x0;
19+
public UByteBuffer $registers;
2020

21-
public int $registerVF = 0x0;
21+
public int $registerI = 0x0;
2222

2323
public UByteBuffer $timers;
2424

@@ -32,15 +32,17 @@ class CPU
3232

3333
private InstructionRegistry $instructionSet;
3434

35+
public bool $wantKeyboardUpdates = true;
36+
3537
public array $digitSpriteLocations = [];
3638

3739
public function __construct(
3840
public Memory $memory,
3941
public Monitor $monitor
4042
)
4143
{
42-
$this->registersV = new UByteBuffer();
43-
$this->registersV->fill(16, 0x0);
44+
$this->registers = new UByteBuffer();
45+
$this->registers->fill(16, 0x0);
4446

4547
$this->timers = new UByteBuffer();
4648
$this->timers->fill(2, 0x0);
@@ -185,16 +187,22 @@ public function disassembleInstructionAt(int $index) : ?string
185187

186188

187189
/**
188-
* Runs the CPU until the program ends
190+
* Runs the CPU until the program ends or the timeout is reached
189191
*/
190-
public function run()
192+
public function run(float $timeout = 60) : int
191193
{
192-
while (true) {
194+
$startTime = microtime(true);
195+
196+
while (!$this->shouldExit) {
197+
if (microtime(true) - $startTime > $timeout) {
198+
return -2;
199+
}
200+
193201
$opcode = $this->fetchOpcode();
194-
echo sprintf('exec: 0x%X' . PHP_EOL, $opcode);
195202
$this->executeOpcode($opcode);
196-
sleep(1);
197203
}
204+
205+
return 0;
198206
}
199207

200208
/**
@@ -209,6 +217,10 @@ public function runFor(float $deltaTimeInMs) : int
209217
$endTime = $startTime + $deltaTimeInMs / 1000.0;
210218

211219
while (microtime(true) < $endTime) {
220+
if ($this->shouldExit) {
221+
return 0;
222+
}
223+
212224
$opcode = $this->fetchOpcode();
213225
$this->executeOpcode($opcode);
214226
}
@@ -225,6 +237,10 @@ public function runFor(float $deltaTimeInMs) : int
225237
public function runCycles(int $count = 1) : int
226238
{
227239
for ($i = 0; $i < $count; $i++) {
240+
if ($this->shouldExit) {
241+
return 0;
242+
}
243+
228244
$opcode = $this->fetchOpcode();
229245
$this->executeOpcode($opcode);
230246
}

0 commit comments

Comments
 (0)