Seregon/ShadPKG

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

C++/47.3 KB/No license
ps4MEL/gnm_driver.cpp
ShadPKG / ps4MEL / gnm_driver.cpp
1/*
2 * ╔═══════════════════════════════════════════════════════════════════════════╗
3 * ║ GNM DRIVER - PS4 Graphics API Layer ║
4 * ╠═══════════════════════════════════════════════════════════════════════════╣
5 * ║ Translates PS4 GNM calls to Vulkan/SDL rendering ║
6 * ╚═══════════════════════════════════════════════════════════════════════════╝
7 */
8 
9#include "gnm_driver.h"
10#include "sdl_backend.h"
11#include <iostream>
12#include <cstring>
13 
14namespace PS4Emu {
15namespace GNM {
16 
17// Statistics
18static uint64_t g_drawCallCount = 0;
19static uint64_t g_frameCount = 0;
20static uint64_t g_submitCount = 0;
21static bool g_initialized = false;
22 
23// Forward declarations
24void ParseCommandBuffer(const void* dcb, uint32_t sizeInBytes);
25 
26// Current render state
27static void* g_currentVsShader = nullptr;
28static void* g_currentPsShader = nullptr;
29static void* g_currentRenderTarget = nullptr;
30static int32_t g_videoOutHandle = -1;
31 
32bool Initialize() {
33 if (g_initialized) return true;
34
35 std::cout << "[GNM] Initializing GNM Driver..." << std::endl;
36 g_drawCallCount = 0;
37 g_frameCount = 0;
38 g_submitCount = 0;
39 g_initialized = true;
40
41 std::cout << "[GNM] GNM Driver initialized (SDL backend)" << std::endl;
42 return true;
43}
44 
45void Shutdown() {
46 if (!g_initialized) return;
47
48 std::cout << "[GNM] Shutting down GNM Driver..." << std::endl;
49 PrintStats();
50 g_initialized = false;
51}
52 
53// ═══════════════════════════════════════════════════════════════════════════
54// COMMAND BUFFER SUBMISSION
55// ═══════════════════════════════════════════════════════════════════════════
56 
57int32_t sceGnmSubmitCommandBuffers(uint32_t count, void** dcbGpuAddrs,
58 uint32_t* dcbSizesInBytes,
59 void** ccbGpuAddrs, uint32_t* ccbSizesInBytes) {
60 g_submitCount++;
61
62 // Parse PM4 command buffers
63 for (uint32_t i = 0; i < count; i++) {
64 if (dcbGpuAddrs && dcbGpuAddrs[i] && dcbSizesInBytes) {
65 ParseCommandBuffer(dcbGpuAddrs[i], dcbSizesInBytes[i]);
66 }
67 }
68
69 if (g_submitCount % 60 == 0) {
70 std::cout << "[GNM] SubmitCommandBuffers: count=" << count
71 << " (total submits: " << g_submitCount << ", draws: " << g_drawCallCount << ")" << std::endl;
72 }
73
74 return 0; // SCE_OK
75}
76 
77int32_t sceGnmSubmitAndFlipCommandBuffers(uint32_t count, void** dcbGpuAddrs,
78 uint32_t* dcbSizesInBytes,
79 void** ccbGpuAddrs, uint32_t* ccbSizesInBytes,
80 int32_t videoOutHandle, int32_t flipArg,
81 void* flipMode, int64_t flipArg2) {
82 // Submit command buffers
83 sceGnmSubmitCommandBuffers(count, dcbGpuAddrs, dcbSizesInBytes,
84 ccbGpuAddrs, ccbSizesInBytes);
85
86 // Flip (present frame)
87 g_frameCount++;
88 SDL::Present();
89
90 if (g_frameCount % 60 == 0) {
91 std::cout << "[GNM] Frame " << g_frameCount << " (draws: " << g_drawCallCount << ")" << std::endl;
92 }
93
94 return 0;
95}
96 
97int32_t sceGnmSubmitDone() {
98 // Signal that all submissions are complete
99 return 0;
100}
101 
102// ═══════════════════════════════════════════════════════════════════════════
103// HARDWARE STATE INITIALIZATION
104// ═══════════════════════════════════════════════════════════════════════════
105 
106int32_t sceGnmDrawInitDefaultHardwareState(void* dcb, uint32_t numDwords) {
107 std::cout << "[GNM] DrawInitDefaultHardwareState" << std::endl;
108 return 0;
109}
110 
111int32_t sceGnmDrawInitDefaultHardwareState350(void* dcb, uint32_t numDwords) {
112 std::cout << "[GNM] DrawInitDefaultHardwareState350" << std::endl;
113 return 0;
114}
115 
116int32_t sceGnmDispatchInitDefaultHardwareState(void* dcb, uint32_t numDwords) {
117 std::cout << "[GNM] DispatchInitDefaultHardwareState" << std::endl;
118 return 0;
119}
120 
121// ═══════════════════════════════════════════════════════════════════════════
122// DRAW COMMANDS
123// ═══════════════════════════════════════════════════════════════════════════
124 
125int32_t sceGnmDrawIndex(void* dcb, uint32_t indexCount, void* indexAddr,
126 uint32_t predAndMod, uint32_t inlineMode) {
127 g_drawCallCount++;
128
129 // In a real implementation, we would:
130 // 1. Bind the current shaders
131 // 2. Set up vertex/index buffers
132 // 3. Issue a Vulkan draw call
133
134 return 0;
135}
136 
137int32_t sceGnmDrawIndexAuto(void* dcb, uint32_t indexCount, uint32_t predAndMod) {
138 g_drawCallCount++;
139 return 0;
140}
141 
142int32_t sceGnmDrawIndexOffset(void* dcb, uint32_t indexOffset, uint32_t indexCount,
143 uint32_t predAndMod) {
144 g_drawCallCount++;
145 return 0;
146}
147 
148// ═══════════════════════════════════════════════════════════════════════════
149// SHADER SETUP
150// ═══════════════════════════════════════════════════════════════════════════
151 
152int32_t sceGnmSetVsShader(void* dcb, void* shader, uint32_t shaderModifier) {
153 g_currentVsShader = shader;
154 return 0;
155}
156 
157int32_t sceGnmSetPsShader(void* dcb, void* shader) {
158 g_currentPsShader = shader;
159 return 0;
160}
161 
162int32_t sceGnmSetCsShader(void* dcb, void* shader) {
163 return 0;
164}
165 
166// ═══════════════════════════════════════════════════════════════════════════
167// RESOURCE BINDING
168// ═══════════════════════════════════════════════════════════════════════════
169 
170int32_t sceGnmSetVSharpInUserData(void* dcb, uint32_t stage, uint32_t startSlot, void* buffer) {
171 return 0;
172}
173 
174int32_t sceGnmSetTSharpInUserData(void* dcb, uint32_t stage, uint32_t startSlot, void* texture) {
175 return 0;
176}
177 
178int32_t sceGnmSetSSharpInUserData(void* dcb, uint32_t stage, uint32_t startSlot, void* sampler) {
179 return 0;
180}
181 
182// ═══════════════════════════════════════════════════════════════════════════
183// RENDER TARGET
184// ═══════════════════════════════════════════════════════════════════════════
185 
186int32_t sceGnmSetRenderTarget(void* dcb, uint32_t rtSlot, void* target) {
187 g_currentRenderTarget = target;
188 return 0;
189}
190 
191int32_t sceGnmSetDepthRenderTarget(void* dcb, void* depthTarget) {
192 return 0;
193}
194 
195// ═══════════════════════════════════════════════════════════════════════════
196// VIDEO OUTPUT
197// ═══════════════════════════════════════════════════════════════════════════
198 
199int32_t sceVideoOutOpen(int32_t userId, int32_t busType, int32_t index, void* param) {
200 std::cout << "[GNM] sceVideoOutOpen: userId=" << userId << std::endl;
201 g_videoOutHandle = 1; // Return a valid handle
202 return g_videoOutHandle;
203}
204 
205int32_t sceVideoOutClose(int32_t handle) {
206 std::cout << "[GNM] sceVideoOutClose: handle=" << handle << std::endl;
207 g_videoOutHandle = -1;
208 return 0;
209}
210 
211int32_t sceVideoOutSetFlipRate(int32_t handle, int32_t rate) {
212 std::cout << "[GNM] sceVideoOutSetFlipRate: rate=" << rate << std::endl;
213 return 0;
214}
215 
216int32_t sceVideoOutSubmitFlip(int32_t handle, int32_t bufferIndex,
217 uint32_t flipMode, int64_t flipArg) {
218 g_frameCount++;
219 SDL::Present();
220 return 0;
221}
222 
223int32_t sceVideoOutRegisterBuffers(int32_t handle, int32_t startIndex,
224 void** addresses, int32_t bufferNum,
225 void* attribute) {
226 std::cout << "[GNM] sceVideoOutRegisterBuffers: bufferNum=" << bufferNum << std::endl;
227 return 0;
228}
229 
230// ═══════════════════════════════════════════════════════════════════════════
231// FRAMEBUFFER MANAGEMENT
232// ═══════════════════════════════════════════════════════════════════════════
233 
234static uint32_t* g_framebuffer = nullptr;
235static uint32_t g_fbWidth = 1920;
236static uint32_t g_fbHeight = 1080;
237static uint32_t g_fbPitch = 1920;
238 
239void SetFramebuffer(uint32_t* pixels, uint32_t width, uint32_t height, uint32_t pitch) {
240 g_framebuffer = pixels;
241 g_fbWidth = width;
242 g_fbHeight = height;
243 g_fbPitch = pitch;
244}
245 
246uint32_t* GetFramebuffer() { return g_framebuffer; }
247uint32_t GetFramebufferWidth() { return g_fbWidth; }
248uint32_t GetFramebufferHeight() { return g_fbHeight; }
249 
250// ═══════════════════════════════════════════════════════════════════════════
251// SOFTWARE RENDERING PRIMITIVES
252// ═══════════════════════════════════════════════════════════════════════════
253 
254void ClearRenderTarget(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
255 if (!g_framebuffer) return;
256 uint32_t color = (a << 24) | (r << 16) | (g << 8) | b;
257 for (uint32_t y = 0; y < g_fbHeight; y++) {
258 for (uint32_t x = 0; x < g_fbWidth; x++) {
259 g_framebuffer[y * g_fbPitch + x] = color;
260 }
261 }
262}
263 
264void DrawRect(int x, int y, int w, int h, uint32_t color) {
265 if (!g_framebuffer) return;
266 for (int py = y; py < y + h && py < (int)g_fbHeight; py++) {
267 if (py < 0) continue;
268 for (int px = x; px < x + w && px < (int)g_fbWidth; px++) {
269 if (px < 0) continue;
270 g_framebuffer[py * g_fbPitch + px] = color;
271 }
272 }
273}
274 
275void DrawTriangle(float x0, float y0, float x1, float y1, float x2, float y2, uint32_t color) {
276 if (!g_framebuffer) return;
277 // Simple bounding box rasterization
278 int minX = (int)std::min({x0, x1, x2});
279 int maxX = (int)std::max({x0, x1, x2});
280 int minY = (int)std::min({y0, y1, y2});
281 int maxY = (int)std::max({y0, y1, y2});
282
283 minX = std::max(0, minX);
284 minY = std::max(0, minY);
285 maxX = std::min((int)g_fbWidth - 1, maxX);
286 maxY = std::min((int)g_fbHeight - 1, maxY);
287
288 for (int py = minY; py <= maxY; py++) {
289 for (int px = minX; px <= maxX; px++) {
290 // Barycentric coordinates
291 float w0 = (x1 - x0) * (py - y0) - (y1 - y0) * (px - x0);
292 float w1 = (x2 - x1) * (py - y1) - (y2 - y1) * (px - x1);
293 float w2 = (x0 - x2) * (py - y2) - (y0 - y2) * (px - x2);
294
295 if ((w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 <= 0 && w1 <= 0 && w2 <= 0)) {
296 g_framebuffer[py * g_fbPitch + px] = color;
297 }
298 }
299 }
300 g_drawCallCount++;
301}
302 
303// ═══════════════════════════════════════════════════════════════════════════
304// PM4 COMMAND BUFFER PARSING
305// ═══════════════════════════════════════════════════════════════════════════
306 
307// PM4 Packet Types
308enum PM4PacketType {
309 PM4_TYPE0 = 0,
310 PM4_TYPE2 = 2,
311 PM4_TYPE3 = 3
312};
313 
314// PM4 Type 3 Opcodes (subset)
315enum PM4Opcode {
316 PM4_NOP = 0x10,
317 PM4_SET_CONTEXT_REG = 0x69,
318 PM4_SET_SH_REG = 0x76,
319 PM4_DRAW_INDEX_2 = 0x27,
320 PM4_DRAW_INDEX_AUTO = 0x2D,
321 PM4_DISPATCH_DIRECT = 0x15,
322 PM4_EVENT_WRITE = 0x46,
323 PM4_EVENT_WRITE_EOP = 0x47,
324 PM4_RELEASE_MEM = 0x49,
325 PM4_ACQUIRE_MEM = 0x58,
326};
327 
328void ParseCommandBuffer(const void* dcb, uint32_t sizeInBytes) {
329 if (!dcb || sizeInBytes < 4) return;
330
331 const uint32_t* cmd = static_cast<const uint32_t*>(dcb);
332 uint32_t offset = 0;
333 uint32_t numDwords = sizeInBytes / 4;
334
335 while (offset < numDwords) {
336 uint32_t header = cmd[offset];
337 uint32_t type = (header >> 30) & 0x3;
338
339 if (type == PM4_TYPE3) {
340 uint32_t opcode = (header >> 8) & 0xFF;
341 uint32_t count = (header & 0x3FFF) + 1;
342
343 switch (opcode) {
344 case PM4_DRAW_INDEX_2:
345 case PM4_DRAW_INDEX_AUTO:
346 g_drawCallCount++;
347 break;
348 case PM4_NOP:
349 break;
350 default:
351 break;
352 }
353
354 offset += count + 1;
355 } else if (type == PM4_TYPE2) {
356 offset++;
357 } else {
358 offset++;
359 }
360 }
361}
362 
363// ═══════════════════════════════════════════════════════════════════════════
364// STATISTICS
365// ═══════════════════════════════════════════════════════════════════════════
366 
367void PrintStats() {
368 std::cout << "[GNM] === GNM Driver Statistics ===" << std::endl;
369 std::cout << "[GNM] Total frames: " << g_frameCount << std::endl;
370 std::cout << "[GNM] Total draw calls: " << g_drawCallCount << std::endl;
371 std::cout << "[GNM] Total submits: " << g_submitCount << std::endl;
372}
373 
374uint64_t GetDrawCallCount() {
375 return g_drawCallCount;
376}
377 
378uint64_t GetFrameCount() {
379 return g_frameCount;
380}
381 
382} // namespace GNM
383} // namespace PS4Emu
384 
385// ═══════════════════════════════════════════════════════════════════════════
386// C-COMPATIBLE EXPORTS for decompiled code
387// ═══════════════════════════════════════════════════════════════════════════
388 
389extern "C" {
390 
391int32_t sceGnmSubmitCommandBuffers(uint32_t count, void** dcbGpuAddrs,
392 uint32_t* dcbSizesInBytes,
393 void** ccbGpuAddrs, uint32_t* ccbSizesInBytes) {
394 return PS4Emu::GNM::sceGnmSubmitCommandBuffers(count, dcbGpuAddrs, dcbSizesInBytes,
395 ccbGpuAddrs, ccbSizesInBytes);
396}
397 
398int32_t sceGnmSubmitAndFlipCommandBuffers(uint32_t count, void** dcbGpuAddrs,
399 uint32_t* dcbSizesInBytes,
400 void** ccbGpuAddrs, uint32_t* ccbSizesInBytes,
401 int32_t videoOutHandle, int32_t flipArg,
402 void* flipMode, int64_t flipArg2) {
403 return PS4Emu::GNM::sceGnmSubmitAndFlipCommandBuffers(count, dcbGpuAddrs, dcbSizesInBytes,
404 ccbGpuAddrs, ccbSizesInBytes,
405 videoOutHandle, flipArg, flipMode, flipArg2);
406}
407 
408int32_t sceGnmSubmitDone() {
409 return PS4Emu::GNM::sceGnmSubmitDone();
410}
411 
412int32_t sceGnmDrawInitDefaultHardwareState(void* dcb, uint32_t numDwords) {
413 return PS4Emu::GNM::sceGnmDrawInitDefaultHardwareState(dcb, numDwords);
414}
415 
416int32_t sceGnmDrawIndex(void* dcb, uint32_t indexCount, void* indexAddr,
417 uint32_t predAndMod, uint32_t inlineMode) {
418 return PS4Emu::GNM::sceGnmDrawIndex(dcb, indexCount, indexAddr, predAndMod, inlineMode);
419}
420 
421int32_t sceGnmDrawIndexAuto(void* dcb, uint32_t indexCount, uint32_t predAndMod) {
422 return PS4Emu::GNM::sceGnmDrawIndexAuto(dcb, indexCount, predAndMod);
423}
424 
425int32_t sceGnmSetVsShader(void* dcb, void* shader, uint32_t shaderModifier) {
426 return PS4Emu::GNM::sceGnmSetVsShader(dcb, shader, shaderModifier);
427}
428 
429int32_t sceGnmSetPsShader(void* dcb, void* shader) {
430 return PS4Emu::GNM::sceGnmSetPsShader(dcb, shader);
431}
432 
433int32_t sceVideoOutOpen(int32_t userId, int32_t busType, int32_t index, void* param) {
434 return PS4Emu::GNM::sceVideoOutOpen(userId, busType, index, param);
435}
436 
437int32_t sceVideoOutClose(int32_t handle) {
438 return PS4Emu::GNM::sceVideoOutClose(handle);
439}
440 
441int32_t sceVideoOutSetFlipRate(int32_t handle, int32_t rate) {
442 return PS4Emu::GNM::sceVideoOutSetFlipRate(handle, rate);
443}
444 
445int32_t sceVideoOutSubmitFlip(int32_t handle, int32_t bufferIndex,
446 uint32_t flipMode, int64_t flipArg) {
447 return PS4Emu::GNM::sceVideoOutSubmitFlip(handle, bufferIndex, flipMode, flipArg);
448}
449 
450int32_t sceVideoOutRegisterBuffers(int32_t handle, int32_t startIndex,
451 void** addresses, int32_t bufferNum,
452 void* attribute) {
453 return PS4Emu::GNM::sceVideoOutRegisterBuffers(handle, startIndex, addresses, bufferNum, attribute);
454}
455 
456} // extern "C"
457