Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
ps4MEL/sdl_backend.cpp
ShadPKG / ps4MEL / sdl_backend.cpp
1/*
2 * ╔═══════════════════════════════════════════════════════════════════════════╗
3 * ║ SDL BACKEND IMPLEMENTATION ║
4 * ╠═══════════════════════════════════════════════════════════════════════════╣
5 * ║ Window, rendering, and input using SDL2. ║
6 * ╚═══════════════════════════════════════════════════════════════════════════╝
7 */
8 
9#include "sdl_backend.h"
10 
11#ifndef PS4_NO_SDL
12#include <SDL2/SDL.h>
13#include <iostream>
14#include <chrono>
15#include <thread>
16 
17namespace PS4Emu {
18namespace SDL {
19 
20// ═══════════════════════════════════════════════════════════════════════════
21// GLOBAL STATE
22// ═══════════════════════════════════════════════════════════════════════════
23 
24static SDL_Window* g_window = nullptr;
25static SDL_Renderer* g_renderer = nullptr;
26static bool g_initialized = false;
27static bool g_shouldQuit = false;
28static bool g_vsyncEnabled = true;
29static PadState g_padState = {};
30static uint64_t g_initTime = 0;
31 
32// Keyboard to PAD mapping
33struct KeyMapping {
34 SDL_Scancode key;
35 uint32_t button;
36};
37 
38static const KeyMapping g_keyMappings[] = {
39 { SDL_SCANCODE_RETURN, PAD_OPTIONS },
40 { SDL_SCANCODE_UP, PAD_UP },
41 { SDL_SCANCODE_DOWN, PAD_DOWN },
42 { SDL_SCANCODE_LEFT, PAD_LEFT },
43 { SDL_SCANCODE_RIGHT, PAD_RIGHT },
44 { SDL_SCANCODE_Z, PAD_CROSS }, // X button
45 { SDL_SCANCODE_X, PAD_CIRCLE }, // O button
46 { SDL_SCANCODE_A, PAD_SQUARE }, // Square
47 { SDL_SCANCODE_S, PAD_TRIANGLE }, // Triangle
48 { SDL_SCANCODE_Q, PAD_L1 },
49 { SDL_SCANCODE_W, PAD_R1 },
50 { SDL_SCANCODE_E, PAD_L2 },
51 { SDL_SCANCODE_R, PAD_R2 },
52 { SDL_SCANCODE_1, PAD_L3 },
53 { SDL_SCANCODE_2, PAD_R3 },
54 { SDL_SCANCODE_SPACE, PAD_TOUCHPAD },
55};
56 
57// ═══════════════════════════════════════════════════════════════════════════
58// INITIALIZATION
59// ═══════════════════════════════════════════════════════════════════════════
60 
61bool Initialize(const std::string& title, int width, int height) {
62 if (g_initialized) {
63 return true;
64 }
65 
66 std::cout << "[SDL] Initializing SDL2..." << std::endl;
67 
68 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) < 0) {
69 std::cerr << "[SDL] Failed to initialize: " << SDL_GetError() << std::endl;
70 return false;
71 }
72 
73 // Create window
74 g_window = SDL_CreateWindow(
75 title.c_str(),
76 SDL_WINDOWPOS_CENTERED,
77 SDL_WINDOWPOS_CENTERED,
78 width,
79 height,
80 SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
81 );
82 
83 if (!g_window) {
84 std::cerr << "[SDL] Failed to create window: " << SDL_GetError() << std::endl;
85 SDL_Quit();
86 return false;
87 }
88 
89 // Create renderer with VSync
90 Uint32 rendererFlags = SDL_RENDERER_ACCELERATED;
91 if (g_vsyncEnabled) {
92 rendererFlags |= SDL_RENDERER_PRESENTVSYNC;
93 }
94 
95 g_renderer = SDL_CreateRenderer(g_window, -1, rendererFlags);
96 if (!g_renderer) {
97 std::cerr << "[SDL] Failed to create renderer: " << SDL_GetError() << std::endl;
98 SDL_DestroyWindow(g_window);
99 SDL_Quit();
100 return false;
101 }
102 
103 // Initialize pad state
104 g_padState.connected = true;
105 g_padState.leftStickX = 128;
106 g_padState.leftStickY = 128;
107 g_padState.rightStickX = 128;
108 g_padState.rightStickY = 128;
109 g_padState.buttons = 0;
110 g_padState.l2 = 0;
111 g_padState.r2 = 0;
112 
113 g_initTime = SDL_GetTicks64();
114 g_initialized = true;
115 g_shouldQuit = false;
116 
117 std::cout << "[SDL] Window created: " << width << "x" << height << std::endl;
118 std::cout << "[SDL] Controls: Arrow keys=D-Pad, Z=X, X=O, A=Square, S=Triangle" << std::endl;
119 std::cout << "[SDL] Q/W=L1/R1, E/R=L2/R2, Enter=Options, Space=Touchpad" << std::endl;
120 
121 return true;
122}
123 
124void Shutdown() {
125 if (!g_initialized) return;
126 
127 std::cout << "[SDL] Shutting down..." << std::endl;
128 
129 if (g_renderer) {
130 SDL_DestroyRenderer(g_renderer);
131 g_renderer = nullptr;
132 }
133 
134 if (g_window) {
135 SDL_DestroyWindow(g_window);
136 g_window = nullptr;
137 }
138 
139 SDL_Quit();
140 g_initialized = false;
141}
142 
143bool IsInitialized() {
144 return g_initialized;
145}
146 
147// ═══════════════════════════════════════════════════════════════════════════
148// WINDOW & RENDERING
149// ═══════════════════════════════════════════════════════════════════════════
150 
151void* GetWindowHandle() {
152 return g_window;
153}
154 
155void* GetRendererHandle() {
156 return g_renderer;
157}
158 
159void* CreateFrameBuffer(int width, int height) {
160 if (!g_renderer) return nullptr;
161
162 SDL_Texture* texture = SDL_CreateTexture(
163 g_renderer,
164 SDL_PIXELFORMAT_ARGB8888,
165 SDL_TEXTUREACCESS_STREAMING,
166 width,
167 height
168 );
169
170 return texture;
171}
172 
173void DestroyFrameBuffer(void* buffer) {
174 if (buffer) {
175 SDL_DestroyTexture(static_cast<SDL_Texture*>(buffer));
176 }
177}
178 
179void UpdateFrameBuffer(void* buffer, const void* pixels, int pitch) {
180 if (!buffer || !pixels) return;
181
182 SDL_UpdateTexture(
183 static_cast<SDL_Texture*>(buffer),
184 nullptr,
185 pixels,
186 pitch
187 );
188}
189 
190void PresentFrameBuffer(void* buffer) {
191 if (!g_renderer || !buffer) return;
192
193 SDL_RenderClear(g_renderer);
194 SDL_RenderCopy(g_renderer, static_cast<SDL_Texture*>(buffer), nullptr, nullptr);
195 SDL_RenderPresent(g_renderer);
196}
197 
198void ClearScreen(uint8_t r, uint8_t g, uint8_t b) {
199 if (!g_renderer) return;
200 SDL_SetRenderDrawColor(g_renderer, r, g, b, 255);
201 SDL_RenderClear(g_renderer);
202}
203 
204void Present() {
205 if (!g_renderer) return;
206 SDL_RenderPresent(g_renderer);
207}
208 
209void SetVSync(bool enabled) {
210 g_vsyncEnabled = enabled;
211 // Note: VSync can only be changed by recreating the renderer
212}
213 
214// ═══════════════════════════════════════════════════════════════════════════
215// INPUT
216// ═══════════════════════════════════════════════════════════════════════════
217 
218void PollEvents() {
219 SDL_Event event;
220
221 while (SDL_PollEvent(&event)) {
222 switch (event.type) {
223 case SDL_QUIT:
224 g_shouldQuit = true;
225 break;
226
227 case SDL_KEYDOWN:
228 case SDL_KEYUP: {
229 bool pressed = (event.type == SDL_KEYDOWN);
230 SDL_Scancode scancode = event.key.keysym.scancode;
231
232 // Check key mappings
233 for (const auto& mapping : g_keyMappings) {
234 if (mapping.key == scancode) {
235 if (pressed) {
236 g_padState.buttons |= mapping.button;
237 } else {
238 g_padState.buttons &= ~mapping.button;
239 }
240 break;
241 }
242 }
243
244 // WASD for left stick
245 const uint8_t* keys = SDL_GetKeyboardState(nullptr);
246
247 // Left stick (IJKL or WASD alternative)
248 g_padState.leftStickX = 128;
249 g_padState.leftStickY = 128;
250 if (keys[SDL_SCANCODE_I]) g_padState.leftStickY = 0; // Up
251 if (keys[SDL_SCANCODE_K]) g_padState.leftStickY = 255; // Down
252 if (keys[SDL_SCANCODE_J]) g_padState.leftStickX = 0; // Left
253 if (keys[SDL_SCANCODE_L]) g_padState.leftStickX = 255; // Right
254
255 // Right stick (numpad or TFGH)
256 g_padState.rightStickX = 128;
257 g_padState.rightStickY = 128;
258 if (keys[SDL_SCANCODE_T]) g_padState.rightStickY = 0;
259 if (keys[SDL_SCANCODE_G]) g_padState.rightStickY = 255;
260 if (keys[SDL_SCANCODE_F]) g_padState.rightStickX = 0;
261 if (keys[SDL_SCANCODE_H]) g_padState.rightStickX = 255;
262
263 // L2/R2 analog (E/R keys give full press)
264 g_padState.l2 = (g_padState.buttons & PAD_L2) ? 255 : 0;
265 g_padState.r2 = (g_padState.buttons & PAD_R2) ? 255 : 0;
266
267 // ESC to quit
268 if (scancode == SDL_SCANCODE_ESCAPE && pressed) {
269 g_shouldQuit = true;
270 }
271 break;
272 }
273
274 case SDL_WINDOWEVENT:
275 if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
276 g_shouldQuit = true;
277 }
278 break;
279 }
280 }
281}
282 
283bool ShouldQuit() {
284 return g_shouldQuit;
285}
286 
287PadState GetPadState() {
288 return g_padState;
289}
290 
291// ═══════════════════════════════════════════════════════════════════════════
292// TIMING
293// ═══════════════════════════════════════════════════════════════════════════
294 
295uint64_t GetTicks() {
296 return SDL_GetTicks64() - g_initTime;
297}
298 
299void Delay(uint32_t ms) {
300 SDL_Delay(ms);
301}
302 
303void WaitVBlank() {
304 // If VSync is enabled, Present() already waits
305 // Otherwise, manually wait for ~16.67ms
306 if (!g_vsyncEnabled) {
307 static auto lastVBlank = std::chrono::steady_clock::now();
308 auto now = std::chrono::steady_clock::now();
309 auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - lastVBlank);
310
311 const auto targetFrame = std::chrono::microseconds(16667); // 60 Hz
312 if (elapsed < targetFrame) {
313 std::this_thread::sleep_for(targetFrame - elapsed);
314 }
315
316 lastVBlank = std::chrono::steady_clock::now();
317 }
318}
319 
320// ═══════════════════════════════════════════════════════════════════════════
321// TEXT AND DIALOG RENDERING
322// ═══════════════════════════════════════════════════════════════════════════
323 
324static std::string g_dialogMessage = "";
325static std::string g_dialogTitle = "";
326 
327// Simple 8x8 bitmap font (subset of ASCII printable characters)
328static const uint8_t g_font8x8[96][8] = {
329 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
330 {0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00}, // !
331 {0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00}, // "
332 {0x36,0x36,0x7F,0x36,0x7F,0x36,0x36,0x00}, // #
333 {0x0C,0x3E,0x03,0x1E,0x30,0x1F,0x0C,0x00}, // $
334 {0x00,0x63,0x33,0x18,0x0C,0x66,0x63,0x00}, // %
335 {0x1C,0x36,0x1C,0x6E,0x3B,0x33,0x6E,0x00}, // &
336 {0x06,0x06,0x03,0x00,0x00,0x00,0x00,0x00}, // '
337 {0x18,0x0C,0x06,0x06,0x06,0x0C,0x18,0x00}, // (
338 {0x06,0x0C,0x18,0x18,0x18,0x0C,0x06,0x00}, // )
339 {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // *
340 {0x00,0x0C,0x0C,0x3F,0x0C,0x0C,0x00,0x00}, // +
341 {0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x06}, // ,
342 {0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, // -
343 {0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x00}, // .
344 {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // /
345 {0x3E,0x63,0x73,0x7B,0x6F,0x67,0x3E,0x00}, // 0
346 {0x0C,0x0E,0x0C,0x0C,0x0C,0x0C,0x3F,0x00}, // 1
347 {0x1E,0x33,0x30,0x1C,0x06,0x33,0x3F,0x00}, // 2
348 {0x1E,0x33,0x30,0x1C,0x30,0x33,0x1E,0x00}, // 3
349 {0x38,0x3C,0x36,0x33,0x7F,0x30,0x78,0x00}, // 4
350 {0x3F,0x03,0x1F,0x30,0x30,0x33,0x1E,0x00}, // 5
351 {0x1C,0x06,0x03,0x1F,0x33,0x33,0x1E,0x00}, // 6
352 {0x3F,0x33,0x30,0x18,0x0C,0x0C,0x0C,0x00}, // 7
353 {0x1E,0x33,0x33,0x1E,0x33,0x33,0x1E,0x00}, // 8
354 {0x1E,0x33,0x33,0x3E,0x30,0x18,0x0E,0x00}, // 9
355 {0x00,0x0C,0x0C,0x00,0x00,0x0C,0x0C,0x00}, // :
356 {0x00,0x0C,0x0C,0x00,0x00,0x0C,0x0C,0x06}, // ;
357 {0x18,0x0C,0x06,0x03,0x06,0x0C,0x18,0x00}, // <
358 {0x00,0x00,0x3F,0x00,0x00,0x3F,0x00,0x00}, // =
359 {0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00}, // >
360 {0x1E,0x33,0x30,0x18,0x0C,0x00,0x0C,0x00}, // ?
361 {0x3E,0x63,0x7B,0x7B,0x7B,0x03,0x1E,0x00}, // @
362 {0x0C,0x1E,0x33,0x33,0x3F,0x33,0x33,0x00}, // A
363 {0x3F,0x66,0x66,0x3E,0x66,0x66,0x3F,0x00}, // B
364 {0x3C,0x66,0x03,0x03,0x03,0x66,0x3C,0x00}, // C
365 {0x1F,0x36,0x66,0x66,0x66,0x36,0x1F,0x00}, // D
366 {0x7F,0x46,0x16,0x1E,0x16,0x46,0x7F,0x00}, // E
367 {0x7F,0x46,0x16,0x1E,0x16,0x06,0x0F,0x00}, // F
368 {0x3C,0x66,0x03,0x03,0x73,0x66,0x7C,0x00}, // G
369 {0x33,0x33,0x33,0x3F,0x33,0x33,0x33,0x00}, // H
370 {0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00}, // I
371 {0x78,0x30,0x30,0x30,0x33,0x33,0x1E,0x00}, // J
372 {0x67,0x66,0x36,0x1E,0x36,0x66,0x67,0x00}, // K
373 {0x0F,0x06,0x06,0x06,0x46,0x66,0x7F,0x00}, // L
374 {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M
375 {0x63,0x67,0x6F,0x7B,0x73,0x63,0x63,0x00}, // N
376 {0x1C,0x36,0x63,0x63,0x63,0x36,0x1C,0x00}, // O
377 {0x3F,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00}, // P
378 {0x1E,0x33,0x33,0x33,0x3B,0x1E,0x38,0x00}, // Q
379 {0x3F,0x66,0x66,0x3E,0x36,0x66,0x67,0x00}, // R
380 {0x1E,0x33,0x07,0x0E,0x38,0x33,0x1E,0x00}, // S
381 {0x3F,0x2D,0x0C,0x0C,0x0C,0x0C,0x1E,0x00}, // T
382 {0x33,0x33,0x33,0x33,0x33,0x33,0x3F,0x00}, // U
383 {0x33,0x33,0x33,0x33,0x33,0x1E,0x0C,0x00}, // V
384 {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W
385 {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X
386 {0x33,0x33,0x33,0x1E,0x0C,0x0C,0x1E,0x00}, // Y
387 {0x7F,0x63,0x31,0x18,0x4C,0x66,0x7F,0x00}, // Z
388 {0x1E,0x06,0x06,0x06,0x06,0x06,0x1E,0x00}, // [
389 {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // backslash
390 {0x1E,0x18,0x18,0x18,0x18,0x18,0x1E,0x00}, // ]
391 {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^
392 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _
393 {0x0C,0x0C,0x18,0x00,0x00,0x00,0x00,0x00}, // `
394 {0x00,0x00,0x1E,0x30,0x3E,0x33,0x6E,0x00}, // a
395 {0x07,0x06,0x06,0x3E,0x66,0x66,0x3B,0x00}, // b
396 {0x00,0x00,0x1E,0x33,0x03,0x33,0x1E,0x00}, // c
397 {0x38,0x30,0x30,0x3E,0x33,0x33,0x6E,0x00}, // d
398 {0x00,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00}, // e
399 {0x1C,0x36,0x06,0x0F,0x06,0x06,0x0F,0x00}, // f
400 {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x1F}, // g
401 {0x07,0x06,0x36,0x6E,0x66,0x66,0x67,0x00}, // h
402 {0x0C,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00}, // i
403 {0x30,0x00,0x30,0x30,0x30,0x33,0x33,0x1E}, // j
404 {0x07,0x06,0x66,0x36,0x1E,0x36,0x67,0x00}, // k
405 {0x0E,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00}, // l
406 {0x00,0x00,0x33,0x7F,0x7F,0x6B,0x63,0x00}, // m
407 {0x00,0x00,0x1F,0x33,0x33,0x33,0x33,0x00}, // n
408 {0x00,0x00,0x1E,0x33,0x33,0x33,0x1E,0x00}, // o
409 {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // p
410 {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // q
411 {0x00,0x00,0x3B,0x6E,0x66,0x06,0x0F,0x00}, // r
412 {0x00,0x00,0x3E,0x03,0x1E,0x30,0x1F,0x00}, // s
413 {0x08,0x0C,0x3E,0x0C,0x0C,0x2C,0x18,0x00}, // t
414 {0x00,0x00,0x33,0x33,0x33,0x33,0x6E,0x00}, // u
415 {0x00,0x00,0x33,0x33,0x33,0x1E,0x0C,0x00}, // v
416 {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w
417 {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x
418 {0x00,0x00,0x33,0x33,0x33,0x3E,0x30,0x1F}, // y
419 {0x00,0x00,0x3F,0x19,0x0C,0x26,0x3F,0x00}, // z
420 {0x38,0x0C,0x0C,0x07,0x0C,0x0C,0x38,0x00}, // {
421 {0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00}, // |
422 {0x07,0x0C,0x0C,0x38,0x0C,0x0C,0x07,0x00}, // }
423 {0x6E,0x3B,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
424 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // DEL
425};
426 
427void DrawText(const char* text, int x, int y, uint8_t r, uint8_t g, uint8_t b) {
428 if (!g_renderer || !text) return;
429
430 SDL_SetRenderDrawColor(g_renderer, r, g, b, 255);
431
432 int curX = x;
433 int curY = y;
434 int scale = 2; // 2x scale for visibility
435
436 for (const char* p = text; *p; p++) {
437 if (*p == '\n') {
438 curX = x;
439 curY += 10 * scale;
440 continue;
441 }
442
443 int charIndex = *p - 32;
444 if (charIndex < 0 || charIndex >= 96) charIndex = 0;
445
446 const uint8_t* glyph = g_font8x8[charIndex];
447 for (int row = 0; row < 8; row++) {
448 for (int col = 0; col < 8; col++) {
449 // Fixed: was (7 - col), now just col for correct orientation
450 if (glyph[row] & (1 << col)) {
451 SDL_Rect pixel = {curX + col * scale, curY + row * scale, scale, scale};
452 SDL_RenderFillRect(g_renderer, &pixel);
453 }
454 }
455 }
456 curX += 8 * scale;
457 }
458}
459 
460void DrawRect(int x, int y, int w, int h, uint8_t r, uint8_t g, uint8_t b, bool filled) {
461 if (!g_renderer) return;
462
463 SDL_SetRenderDrawColor(g_renderer, r, g, b, 255);
464 SDL_Rect rect = {x, y, w, h};
465
466 if (filled) {
467 SDL_RenderFillRect(g_renderer, &rect);
468 } else {
469 SDL_RenderDrawRect(g_renderer, &rect);
470 }
471}
472 
473void SetDialogMessage(const char* message) {
474 if (message) {
475 g_dialogMessage = message;
476 }
477}
478 
479const char* GetCurrentDialogMessage() {
480 return g_dialogMessage.c_str();
481}
482 
483void ShowDialog(const char* title, const char* message) {
484 if (!g_renderer) return;
485
486 g_dialogTitle = title ? title : "";
487 g_dialogMessage = message ? message : "";
488
489 // Draw dialog box
490 int winW = 800, winH = 600;
491 int boxW = 500, boxH = 200;
492 int boxX = (winW - boxW) / 2;
493 int boxY = (winH - boxH) / 2;
494
495 // Background
496 DrawRect(boxX, boxY, boxW, boxH, 40, 40, 80, true);
497 // Border
498 DrawRect(boxX, boxY, boxW, boxH, 100, 100, 200, false);
499 DrawRect(boxX+2, boxY+2, boxW-4, boxH-4, 80, 80, 160, false);
500
501 // Title bar
502 DrawRect(boxX, boxY, boxW, 30, 60, 60, 120, true);
503 DrawText(title, boxX + 10, boxY + 8, 255, 255, 255);
504
505 // Message
506 DrawText(message, boxX + 20, boxY + 50, 220, 220, 255);
507
508 // OK button hint
509 DrawText("Press X to continue", boxX + 150, boxY + boxH - 35, 150, 150, 200);
510}
511 
512} // namespace SDL
513} // namespace PS4Emu
514 
515#else // PS4_NO_SDL - provide no-op stubs
516 
517#include <iostream>
518 
519namespace PS4Emu {
520namespace SDL {
521 
522bool Initialize(const std::string& title, int width, int height) {
523 std::cout << "[SDL] No-SDL stub: Initialize(\"" << title << "\")" << std::endl;
524 return true;
525}
526void Shutdown() {}
527bool IsInitialized() { return false; }
528void* GetWindowHandle() { return nullptr; }
529void* GetRendererHandle() { return nullptr; }
530void* CreateFrameBuffer(int, int) { return nullptr; }
531void DestroyFrameBuffer(void*) {}
532void UpdateFrameBuffer(void*, const void*, int) {}
533void PresentFrameBuffer(void*) {}
534void ClearScreen(uint8_t, uint8_t, uint8_t) {}
535void Present() {}
536void SetVSync(bool) {}
537void DrawText(const char*, int, int, uint8_t, uint8_t, uint8_t) {}
538void DrawRect(int, int, int, int, uint8_t, uint8_t, uint8_t, bool) {}
539void ShowDialog(const char* title, const char* message) {
540 std::cout << "[DIALOG] " << (title ? title : "") << ": " << (message ? message : "") << std::endl;
541}
542void SetDialogMessage(const char*) {}
543const char* GetCurrentDialogMessage() { return ""; }
544void PollEvents() {}
545bool ShouldQuit() { return false; }
546PadState GetPadState() { return PadState{}; }
547uint64_t GetTicks() { return 0; }
548void Delay(uint32_t) {}
549void WaitVBlank() {}
550 
551} // namespace SDL
552} // namespace PS4Emu
553 
554#endif // PS4_NO_SDL
555