1 #include "rdp_dump.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 static FILE *rdp_file;
7 static uint8_t *rdp_dram_cache;
8 static uint8_t *rdp_hidden_dram_cache;
9
10 enum rdp_dump_cmd
11 {
12 RDP_DUMP_CMD_INVALID = 0,
13 RDP_DUMP_CMD_UPDATE_DRAM = 1,
14 RDP_DUMP_CMD_RDP_COMMAND = 2,
15 RDP_DUMP_CMD_SET_VI_REGISTER = 3,
16 RDP_DUMP_CMD_END_FRAME = 4,
17 RDP_DUMP_CMD_SIGNAL_COMPLETE = 5,
18 RDP_DUMP_CMD_EOF = 6,
19 RDP_DUMP_CMD_UPDATE_DRAM_FLUSH = 7,
20 RDP_DUMP_CMD_UPDATE_HIDDEN_DRAM = 8,
21 RDP_DUMP_CMD_UPDATE_HIDDEN_DRAM_FLUSH = 9,
22 RDP_DUMP_CMD_INT_MAX = 0x7fffffff
23 };
24
rdp_dump_init(const char * path,uint32_t dram_size,uint32_t hidden_dram_size)25 bool rdp_dump_init(const char *path, uint32_t dram_size, uint32_t hidden_dram_size)
26 {
27 if (rdp_file)
28 return false;
29
30 free(rdp_dram_cache);
31 rdp_dram_cache = calloc(1, dram_size);
32 if (!rdp_dram_cache)
33 return false;
34 rdp_hidden_dram_cache = calloc(1, hidden_dram_size);
35 if (!rdp_hidden_dram_cache)
36 {
37 free(rdp_dram_cache);
38 rdp_dram_cache = NULL;
39 return false;
40 }
41
42 rdp_file = fopen(path, "wb");
43 if (!rdp_file)
44 {
45 free(rdp_dram_cache);
46 free(rdp_hidden_dram_cache);
47 rdp_dram_cache = NULL;
48 rdp_hidden_dram_cache = NULL;
49 return false;
50 }
51
52 fwrite("RDPDUMP2", 8, 1, rdp_file);
53 fwrite(&dram_size, sizeof(dram_size), 1, rdp_file);
54 fwrite(&hidden_dram_size, sizeof(hidden_dram_size), 1, rdp_file);
55 return true;
56 }
57
rdp_dump_end_frame(void)58 void rdp_dump_end_frame(void)
59 {
60 if (!rdp_file)
61 return;
62
63 uint32_t cmd = RDP_DUMP_CMD_END_FRAME;
64 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
65 }
66
rdp_dump_end(void)67 void rdp_dump_end(void)
68 {
69 if (!rdp_file)
70 return;
71
72 uint32_t cmd = RDP_DUMP_CMD_EOF;
73 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
74
75 fclose(rdp_file);
76 rdp_file = NULL;
77
78 free(rdp_dram_cache);
79 rdp_dram_cache = NULL;
80 free(rdp_hidden_dram_cache);
81 rdp_hidden_dram_cache = NULL;
82 }
83
rdp_dump_flush(const void * dram_,uint32_t size,enum rdp_dump_cmd block_cmd,enum rdp_dump_cmd flush_cmd,uint8_t * cache)84 static void rdp_dump_flush(const void *dram_, uint32_t size,
85 enum rdp_dump_cmd block_cmd, enum rdp_dump_cmd flush_cmd, uint8_t *cache)
86 {
87 if (!rdp_file)
88 return;
89
90 const uint8_t *dram = dram_;
91 const uint32_t block_size = 4 * 1024;
92 uint32_t i = 0;
93
94 for (i = 0; i < size; i += block_size)
95 {
96 if (memcmp(dram + i, cache + i, block_size))
97 {
98 uint32_t cmd = block_cmd;
99 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
100 fwrite(&i, sizeof(i), 1, rdp_file);
101 fwrite(&block_size, sizeof(block_size), 1, rdp_file);
102 fwrite(dram + i, 1, block_size, rdp_file);
103 memcpy(cache + i, dram + i, block_size);
104 }
105 }
106
107 uint32_t cmd = flush_cmd;
108 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
109
110 }
111
rdp_dump_flush_dram(const void * dram_,uint32_t size)112 void rdp_dump_flush_dram(const void *dram_, uint32_t size)
113 {
114 rdp_dump_flush(dram_, size, RDP_DUMP_CMD_UPDATE_DRAM, RDP_DUMP_CMD_UPDATE_DRAM_FLUSH, rdp_dram_cache);
115 }
116
rdp_dump_flush_hidden_dram(const void * dram_,uint32_t size)117 void rdp_dump_flush_hidden_dram(const void *dram_, uint32_t size)
118 {
119 rdp_dump_flush(dram_, size, RDP_DUMP_CMD_UPDATE_HIDDEN_DRAM, RDP_DUMP_CMD_UPDATE_HIDDEN_DRAM_FLUSH, rdp_hidden_dram_cache);
120 }
121
rdp_dump_signal_complete(void)122 void rdp_dump_signal_complete(void)
123 {
124 if (!rdp_file)
125 return;
126
127 uint32_t cmd = RDP_DUMP_CMD_SIGNAL_COMPLETE;
128 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
129 }
130
rdp_dump_emit_command(uint32_t command,const uint32_t * cmd_data,uint32_t cmd_words)131 void rdp_dump_emit_command(uint32_t command, const uint32_t *cmd_data, uint32_t cmd_words)
132 {
133 if (!rdp_file)
134 return;
135
136 uint32_t cmd = RDP_DUMP_CMD_RDP_COMMAND;
137 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
138 fwrite(&command, sizeof(command), 1, rdp_file);
139 fwrite(&cmd_words, sizeof(cmd_words), 1, rdp_file);
140 fwrite(cmd_data, sizeof(*cmd_data), cmd_words, rdp_file);
141 }
142
rdp_dump_set_vi_register(uint32_t vi_register,uint32_t value)143 void rdp_dump_set_vi_register(uint32_t vi_register, uint32_t value)
144 {
145 if (!rdp_file)
146 return;
147
148 uint32_t cmd = RDP_DUMP_CMD_SET_VI_REGISTER;
149 fwrite(&cmd, sizeof(cmd), 1, rdp_file);
150 fwrite(&vi_register, sizeof(vi_register), 1, rdp_file);
151 fwrite(&value, sizeof(value), 1, rdp_file);
152 }
153