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