1 #include <string>
2 #include <unordered_map>
3 #include <vector>
4 #include <3ds.h>
5 #include <arpa/inet.h>
6 #include <malloc.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <sys/socket.h>
10
11 #include "cdc_bin.h"
12
13
14 PrintConsole topScreen, bottomScreen;
15
MoveCursor(unsigned row,unsigned col)16 void MoveCursor(unsigned row, unsigned col) {
17 printf("\x1b[%u;%uH", row + 1, col + 1);
18 }
19
20 enum Color {
21 Reset = 0,
22 Black = 30,
23 Red = 31,
24 Green = 32,
25 Yellow = 33,
26 Blue = 34,
27 Magnenta = 35,
28 Cyan = 36,
29 White = 37,
30 };
SetColor(Color color,Color background)31 void SetColor(Color color, Color background) {
32 printf("\x1b[%dm\x1b[%dm", (int)color, (int)background + 10);
33 }
34
35
36
FlushCache(void * ptr,u32 size)37 void FlushCache(void* ptr, u32 size) {
38 svcFlushProcessDataCache(CUR_PROCESS_HANDLE, ptr, size);
39 }
40
InvalidateCache(void * ptr,u32 size)41 void InvalidateCache(void* ptr, u32 size) {
42 svcInvalidateProcessDataCache(CUR_PROCESS_HANDLE, ptr, size);
43 }
44
45
46 vu16* dspP = (vu16*)0x1FF00000;
47 vu16* dspD = (vu16*)0x1FF40000;
48
49 u32 playground_size = 0x80;
50
51 vu8* dsp_playground = (vu8*)(dspD + 0x1000); // note: address = 0x1000 in dsp space
52 vu8* fcram_playground;
53
PrintAll()54 void PrintAll() {
55 consoleSelect(&topScreen);
56
57 MoveCursor(0, 0);
58 printf("DSP @ 0x1000:\n");
59
60 InvalidateCache((void*)dsp_playground, playground_size);
61 for (u32 i = 0; i < playground_size; ++i) {
62 u8 v = dsp_playground[i];
63 if (v != i) {
64 SetColor(Green, Black);
65 }
66 printf("%02X", v);
67 SetColor(Reset, Reset);
68 if (i % 16 == 15) {
69 printf("\n");
70 } else {
71 printf(" ");
72 }
73 }
74
75
76 u32 addr = (u32)fcram_playground;
77 if (addr < 0x1C000000) {
78 addr = addr - 0x14000000 + 0x20000000;
79 } else {
80 addr = addr - 0x30000000 + 0x20000000;
81 }
82 printf("\nFCRAM @ 0x%08lX:\n", addr);
83
84 InvalidateCache((void*)fcram_playground, playground_size);
85 for (u32 i = 0; i < playground_size; ++i) {
86 u8 v = fcram_playground[i];
87 if (v != (i | 0x80)) {
88 SetColor(Green, Black);
89 }
90 printf("%02X", v);
91 SetColor(Reset, Reset);
92 if (i % 16 == 15) {
93 printf("\n");
94 } else {
95 printf(" ");
96 }
97 }
98
99
100 consoleSelect(&bottomScreen);
101 }
102
ResetDspPlayground()103 void ResetDspPlayground() {
104 InvalidateCache((void*)dsp_playground, playground_size);
105 for (u32 i = 0; i < playground_size; ++i) {
106 dsp_playground[i] = i;
107 }
108 FlushCache((void*)dsp_playground, playground_size);
109 }
110
ResetFcramPlayground()111 void ResetFcramPlayground() {
112 InvalidateCache((void*)fcram_playground, playground_size);
113 for (u32 i = 0; i < playground_size; ++i) {
114 fcram_playground[i] = i | 0x80;
115 }
116 FlushCache((void*)fcram_playground, playground_size);
117 }
118
119 int udp_s;
120 int udp_s_broadcast;
121
UdpInit()122 void UdpInit() {
123 #define SOC_ALIGN 0x1000
124 #define SOC_BUFFERSIZE 0x100000
125 static u32* SOC_buffer;
126 // allocate buffer for SOC service
127 SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
128 if (SOC_buffer == NULL) {
129 printf("memalign: failed to allocate\n");
130 return;
131 }
132
133 Result ret;
134 if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) {
135 printf("socInit: 0x%08lX\n", ret);
136 return;
137 }
138
139 sockaddr_in si_me;
140
141 // create a UDP socket
142 if ((udp_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
143 printf("socket() failed\n");
144 return;
145 }
146
147 // zero out the structure
148 memset(&si_me, 0, sizeof(si_me));
149
150 si_me.sin_family = AF_INET;
151 si_me.sin_port = htons(8888);
152 si_me.sin_addr.s_addr = htonl(INADDR_ANY);
153
154 // bind socket to port
155 if (bind(udp_s, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
156 printf("bind() failed\n");
157 return;
158 }
159
160 // create a UDP broadcast socket
161 if ((udp_s_broadcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
162 printf("socket()(broadcast) failed\n");
163 return;
164 }
165 }
166
167 constexpr unsigned BUFLEN = 512;
168 char buf[BUFLEN];
169
Fire()170 void Fire() {
171 dspD[0] = 1;
172 FlushCache((void*)dspD, 8);
173 while(true) {
174 InvalidateCache((void*)dspD, 8);
175 if (dspD[0] == 0)
176 break;
177 }
178 }
179
CheckPackage()180 void CheckPackage() {
181 sockaddr_in si_other;
182 socklen_t slen = sizeof(si_other);
183 int recv_len;
184 if ((recv_len = recvfrom(udp_s, buf, BUFLEN, MSG_DONTWAIT, (sockaddr*)&si_other, &slen)) < 4)
185 return;
186 u16 magic;
187 memcpy(&magic, buf, 2);
188 if (magic == 0xD592) {
189 std::vector<u16> command_package((recv_len - 2) / 2);
190 printf("Command received\n");
191 memcpy(command_package.data(), buf + 2, command_package.size() * 2);
192 switch (command_package[0]) {
193 case 0: {
194 if (command_package.size() != 2) {
195 printf("Wrong length for Read\n");
196 break;
197 }
198 u16 addr = command_package[1];
199 printf("Read [%04X] -> ", addr);
200 dspD[1] = 0;
201 dspD[2] = addr;
202 dspD[3] = 0xCCCC;
203
204 Fire();
205
206 printf("%04X\n", dspD[3]);
207 break;
208 }
209 case 1: {
210 if (command_package.size() != 3) {
211 printf("Wrong length for Write\n");
212 break;
213 }
214 u16 addr = command_package[1];
215 u16 value = command_package[2];
216 printf("Write [%04X] <- %04X", addr, value);
217 dspD[1] = 1;
218 dspD[2] = addr;
219 dspD[3] = value;
220
221 Fire();
222
223 printf(" OK\n");
224 break;
225 }
226 }
227 }
228 }
229
main()230 int main() {
231 fcram_playground = (vu8*)linearAlloc(playground_size);
232 ResetDspPlayground();
233 ResetFcramPlayground();
234 aptInit();
235 gfxInitDefault();
236
237 consoleInit(GFX_TOP, &topScreen);
238 consoleInit(GFX_BOTTOM, &bottomScreen);
239
240 consoleSelect(&bottomScreen);
241 printf("Hello!\n");
242
243 UdpInit();
244
245 printf("dspInit: %08lX\n", dspInit());
246 bool loaded = false;
247 printf("DSP_LoadComponent: %08lX\n",
248 DSP_LoadComponent(cdc_bin, cdc_bin_size, 0xFF, 0xFF, &loaded));
249 printf("loaded = %d\n", loaded);
250
251 svcSleepThread(1000000000);
252 char hostname[100];
253 gethostname(hostname, 100);
254 printf("IP: %s port: 8888\n", hostname);
255
256 // Main loop
257 while (aptMainLoop()) {
258 hidScanInput();
259
260 u32 kDown = hidKeysDown();
261
262 if (kDown & KEY_START)
263 break;
264
265 if (kDown & KEY_A) {
266 ResetDspPlayground();
267 printf("Reset DSP playground\n");
268 }
269
270 if (kDown & KEY_B) {
271 ResetFcramPlayground();
272 printf("Reset FCRAM playground\n");
273 }
274
275 CheckPackage();
276
277 PrintAll();
278
279 // Flush and swap framebuffers
280 gfxFlushBuffers();
281 gfxSwapBuffers();
282
283 // Wait for VBlank
284 gspWaitForVBlank();
285 }
286 socExit();
287 dspExit();
288 gfxExit();
289 aptExit();
290 return 0;
291 }
292