feat: more opcode coverage
1 files changed, 414 insertions(+), 291 deletions(-) | |||
---|---|---|---|
M | main.c | +414 | -291 |
1@@ -63,7 +63,7 @@ unsigned char chip8_fontset[80] = {
2 0xF0, 0x80, 0x80, 0x80, 0xF0, // C
3 0xE0, 0x90, 0x90, 0x90, 0xE0, // D
4 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
5- 0xF0, 0x80, 0xF0, 0x80, 0x80 // F
6+ 0xF0, 0x80, 0xF0, 0x80, 0x80 // F
7 };
8
9 // Keypad
10@@ -74,317 +74,440 @@ const int SCREEN_WIDTH = 64 * 10;
11 const int SCREEN_HEIGHT = 32 * 10;
12
13 /*** initialize CPU ***/
14-void chip8_initialize(void) {
15- // Seed for rand from time.h
16- srand((unsigned int)time(NULL));
17- pc = 0x200; // program counter starts at 0x200 or 512
18- opcode = 0; // reset current opcode
19- I = 0; // reset current index register
20- stack_pointer = 0; // reset stack pointer
21- printf("\n Chip 8 Initialized successfully \n");
22- memcpy(memory, chip8_fontset, sizeof(chip8_fontset));
23+void chip8_initialize(void)
24+{
25+ // Seed for rand from time.h
26+ srand((unsigned int)time(NULL));
27+ pc = 0x200; // program counter starts at 0x200 or 512
28+ opcode = 0; // reset current opcode
29+ I = 0; // reset current index register
30+ stack_pointer = 0; // reset stack pointer
31+ printf("\n Chip 8 Initialized successfully \n");
32+ memcpy(memory, chip8_fontset, sizeof(chip8_fontset));
33 }
34
35 /*** load rom ***/
36-void chip8_load_program(char *filename) {
37- FILE *program = fopen(filename, "rb");
38-
39- // get file size
40- fseek(program, 0, SEEK_END);
41- long buf_len = ftell(program);
42- rewind(program);
43-
44- // load data into buffer
45- char *buf = malloc((buf_len + 1) * sizeof(char));
46- fread(buf, buf_len, 1, program);
47- printf("Rom loaded succesfully \n");
48- printf("Rom size: %zu bytes \n", buf_len);
49- fclose(program);
50-
51- // load ROM into memory
52- for (int i = 0; i < buf_len; i++) {
53- memory[0x200 + i] = buf[i];
54- // Big endian so check last two values from the right
55- printf("Byte successfully read: %08X \n", buf[i]);
56- }
57- // clear buffer
58- free(buf);
59+void chip8_load_program(char* filename)
60+{
61+ FILE* program = fopen(filename, "rb");
62+
63+ // get file size
64+ fseek(program, 0, SEEK_END);
65+ long buf_len = ftell(program);
66+ rewind(program);
67+
68+ // load data into buffer
69+ char* buf = malloc((buf_len + 1) * sizeof(char));
70+ fread(buf, buf_len, 1, program);
71+ printf("Rom loaded succesfully \n");
72+ printf("Rom size: %zu bytes \n", buf_len);
73+ fclose(program);
74+
75+ // load ROM into memory
76+ for (int i = 0; i < buf_len; i++) {
77+ memory[0x200 + i] = buf[i];
78+ // Big endian so check last two values from the right
79+ printf("Byte successfully read: %08X \n", buf[i]);
80+ }
81+ // clear buffer
82+ free(buf);
83 }
84
85 /*** initialize display ***/
86
87-SDL_Window *window;
88-SDL_Renderer *renderer;
89-
90-int chip8_init_display() {
91- SDL_Init(SDL_INIT_VIDEO);
92- // Init Window struct
93-
94- // Init window
95- window =
96- SDL_CreateWindow("CHIP8", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
97- SCREEN_WIDTH, SCREEN_HEIGHT, 0);
98- // Init renderer struct
99- renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
100-
101- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
102- printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
103- return -1;
104- }
105- // Check that the window was successfully created
106-
107- if (window == NULL) {
108- // In the case that the window could not be made...
109- printf("Could not create window: %s\n", SDL_GetError());
110- return -1;
111- }
112- return 0;
113+SDL_Window* window;
114+SDL_Renderer* renderer;
115+
116+int chip8_init_display()
117+{
118+ SDL_Init(SDL_INIT_VIDEO);
119+ // Init Window struct
120+
121+ // Init window
122+ window = SDL_CreateWindow("CHIP8",
123+ SDL_WINDOWPOS_CENTERED,
124+ SDL_WINDOWPOS_CENTERED,
125+ SCREEN_WIDTH,
126+ SCREEN_HEIGHT,
127+ 0);
128+ // Init renderer struct
129+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
130+
131+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
132+ printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
133+ return -1;
134+ }
135+ // Check that the window was successfully created
136+
137+ if (window == NULL) {
138+ // In the case that the window could not be made...
139+ printf("Could not create window: %s\n", SDL_GetError());
140+ return -1;
141+ }
142+ return 0;
143 }
144
145-void stop_display(void) {
146- SDL_DestroyWindow(window);
147- SDL_Quit();
148+void stop_display(void)
149+{
150+ SDL_DestroyWindow(window);
151+ SDL_Quit();
152 }
153
154-void chip8_draw(unsigned char *gfx) {
155- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
156- // Init renderer
157- SDL_RenderClear(renderer);
158- // SDL Render color (background)
159-
160- // Clear the current color and use the one specified above
161- SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
162-
163- for (int y = 0; y < 32; y++) {
164- for (int x = 0; x < 64; x++) {
165- if (gfx[x + (y * 64)]) {
166- SDL_Rect rect;
167- rect.x = x * 10;
168- rect.y = y * 10;
169- rect.w = 10;
170- rect.h = 10;
171-
172- SDL_RenderFillRect(renderer, &rect);
173- }
174+void chip8_draw(unsigned char* gfx)
175+{
176+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
177+ // Init renderer
178+ SDL_RenderClear(renderer);
179+ // SDL Render color (background)
180+
181+ // Clear the current color and use the one specified above
182+ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
183+
184+ for (int y = 0; y < 32; y++) {
185+ for (int x = 0; x < 64; x++) {
186+ if (gfx[x + (y * 64)]) {
187+ SDL_Rect rect;
188+ rect.x = x * 10;
189+ rect.y = y * 10;
190+ rect.w = 10;
191+ rect.h = 10;
192+
193+ SDL_RenderFillRect(renderer, &rect);
194+ }
195+ }
196 }
197- }
198- SDL_RenderPresent(renderer);
199+ SDL_RenderPresent(renderer);
200 }
201
202-void chip8_emulate_cycle() {
203- draw_flag = 0;
204- sound_flag = 0;
205- printf(" \n");
206-
207- // Fetch opcode present at program counter and program counter + 1
208- // Since each opcode is supposed to be 2 bytes we fetch both pc and pc + 1
209- // Shift the current 8 bytes in memory[pc] left by 8 points
210- // We merge them using binary OR to get the entire opcode
211- opcode = memory[pc] << 8 | memory[pc + 1];
212-
213- // Vx register, we are basically "grabbing" the x present in some
214- // instructions like 3XNN
215- unsigned short x = (opcode & 0x0F00) >> 8;
216-
217- // Vy register, we are basically "grabbing" the y present in some
218- // instructions like 5XY0
219- unsigned short y = (opcode & 0x00F0) >> 4;
220-
221- printf("0x%X \n", opcode);
222- switch (opcode & 0xF000) {
223- case 0x0000:
224- for (int i = 0; i < 64 * 32; i++) {
225- gfx[i] = 0;
226- }
227- printf("00E0: Display Cleared\n");
228- pc += 2;
229- break;
230-
231- case 0xC000:
232- V[x] = (rand() % 256) & (opcode & 0x00FF);
233- pc += 2;
234- printf("Cxkk: The value at V[x] is %d \n", V[x]);
235- break;
236-
237- case 0xA000:
238- I = opcode & 0x0FFF;
239- pc += 2;
240- printf("Annn: The value at register I is set to 0x%X \n", opcode & 0x0FFF);
241- break;
242-
243- // set of of 7 instructions starting with FX
244- case 0xF000:
245- switch (opcode & 0x00FF) {
246- case 0x0007:
247- printf("Fx07: Place value of delay_timer into V[x]\n");
248- V[x] = delay_timer;
249- pc += 2;
250- break;
251-
252- case 0x000A:
253- printf("Fx0A: Stop all execution till key press, keypress is stored in V[x]\n");
254- for (int i = 0; i < 16; i++) {
255- if (keypad[i]) {
256- V[x] = i;
257+void chip8_emulate_cycle()
258+{
259+ draw_flag = 0;
260+ sound_flag = 0;
261+ printf(" \n");
262+
263+ // Fetch opcode present at program counter and program counter + 1
264+ // Since each opcode is supposed to be 2 bytes we fetch both pc and pc + 1
265+ // Shift the current 8 bytes in memory[pc] left by 8 points
266+ // We merge them using binary OR to get the entire opcode
267+ opcode = memory[pc] << 8 | memory[pc + 1];
268+
269+ // Vx register, we are basically "grabbing" the x present in some
270+ // instructions like 3XNN
271+ unsigned short x = (opcode & 0x0F00) >> 8;
272+
273+ // Vy register, we are basically "grabbing" the y present in some
274+ // instructions like 5XY0
275+ unsigned short y = (opcode & 0x00F0) >> 4;
276+
277+ printf("0x%X \n", opcode);
278+ switch (opcode & 0xF000) {
279+ case 0x0000:
280+ for (int i = 0; i < 64 * 32; i++) {
281+ gfx[i] = 0;
282+ }
283+ printf("00E0: Display Cleared\n");
284+ pc += 2;
285+ break;
286+
287+ case 0xC000:
288+ V[x] = (rand() % 256) & (opcode & 0x00FF);
289 pc += 2;
290+ printf("Cxkk: The value at V[x] is %d \n", V[x]);
291 break;
292- }
293+
294+ case 0xA000:
295+ I = opcode & 0x0FFF;
296+ pc += 2;
297+ printf("Annn: The value at register I is set to 0x%X \n",
298+ opcode & 0x0FFF);
299+ break;
300+
301+ // 2nnn CALL subroutine at nnn
302+ case 0x2000:
303+ stack_pointer += 1;
304+ stack[stack_pointer] = pc;
305+ pc = opcode & 0x0FFF; // parse the NNN
306+ printf("2nnn: Calls subroutine at nnn \n");
307+ break;
308+
309+ // 3XNN: Skip next instruction if Vx = kk
310+ case 0x3000:
311+ if (V[x] == (opcode & 0x00FF)) {
312+ pc += 2;
313 }
314- break;
315-
316- case 0x0015:
317- printf("Fx15: Sets the delay_timer value to V[x]\n");
318- delay_timer = V[x];
319- pc += 2;
320- break;
321-
322- // FX18: Sets the sound timer to Vx
323- case 0x0018:
324- printf("Fx18: Sets the sound_timer value to V[x]\n");
325- sound_timer = V[x];
326- pc += 2;
327- break;
328-
329- // FX1E: Adds Vx to I
330- case 0x001E:
331- printf("Fx1E:The values of I and Vx are added, and the results are stored in I\n");
332- I += V[x];
333- pc += 2;
334- break;
335-
336- // FX29: Sets I to the location of the sprite for the character
337- // in Vx
338- case 0x0029:
339- printf("Fx29: Set location of I to mathching 0x sprite in V[x] \n");
340- // Each digit contains 5 bytes
341- I = V[x] * 5;
342- pc += 2;
343- break;
344-
345- /*
346- * FX33:
347- *
348- * Stores the binary-coded decimal representation
349- * of VX, with the most significant of three digits
350- * at the address in I, the middle digit at I plus
351- * 1, and the least significant digit at I plus 2.
352- * (In other words, take the decimal representation
353- * of VX, place the hundreds digit in memory
354- * at location in I, the tens digit at
355- * location I+1, and the ones digit at
356- * location I+2.)
357- * */
358-
359- case 0x0033:
360- printf("Fx33: Stores the binary-coded decimal representation of VX \n");
361- memory[I] = (V[x] % 1000) / 100;
362- memory[I + 1] = (V[x] % 100) / 10;
363- memory[I + 2] = (V[x] % 10);
364-
365- pc += 2;
366- break;
367-
368- case 0x0055:
369- printf("Fx55: Stores V[0] to V[x] in memory starting at I\n");
370-
371- for (int i = 0; i <= x; i++) {
372- V[i] = memory[I + i];
373- }
374-
375- pc += 2;
376- break;
377-
378- // Fills V0 through Vx (Vx included) with values from memory
379- // starting at addr I.
380- case 0x0065:
381- printf("Read registers V0 through Vx from memory starting at location I \n");
382- for (int i = 0; i <= x; i++) {
383- V[i] = memory[I + i];
384- }
385- pc += 2;
386- break;
387+ pc += 2;
388+ printf("3XNN: Skip next instruction if V[x] == kk \n");
389+ break;
390
391- default:
392- printf("Fx65: Read registers V[0] through V[x] from memory starting at I.\n");
393- break;
394- }
395-
396- break;
397-
398-
399- // 6XNN: Sets Vx to NN
400- case 0x6000:
401- V[x] = (opcode & 0x00FF);
402- pc += 2;
403- printf("6xkk: The interpreter puts the value kk into register V[x] \n");
404- break;
405-
406- // 1NNN: Jumps to address NNN
407- case 0x1000:
408- printf("1nnn: Jump to location nnn \n");
409- pc = opcode & 0x0FFF;
410- break;
411-
412- // Display n-byte sprite starting at memory location I at (Vx, Vy)
413- // Set VF = collision.
414- case 0xD000:
415- draw_flag = 1;
416- unsigned short height = opcode & 0x000F;
417- unsigned short pixel;
418- // set collision flag to 0
419- V[0xF] = 0;
420- // loop over each row
421- for (int row = 0; row < height; row++) {
422- // fetch the pixel value from the memory starting at location I
423- pixel = memory[I + row];
424- // loop over 8 bits of one row
425- for (int col = 0; col < 10; col++) {
426- // check if current evaluated pixel is set to 1 (0x80 >>
427- // col scnas throught the byte, one bit at the time)
428- if ((pixel & (0x80 >> col)) != 0) {
429- // if drawing causes any pixel to be erased set the
430- // collision flag to 1
431- if (gfx[(V[x] + col + ((V[y] + row) * 64))] == 1) {
432- V[0xF] = 1;
433- }
434- // set pixel value by using XOR
435- gfx[V[x] + col + ((V[y] + row) * 64)] ^= 1;
436+ // 4xkk: Skip next instruction if V[x] != kk
437+ case 0x4000:
438+ if (V[x] != (opcode & 0x00FF)) {
439+ pc += 2;
440 }
441- }
442+ pc += 2;
443+ printf("4xkk: Skip next instruction if V[x] != kk \n");
444+ break;
445+
446+ // 6XNN: Sets Vx to NN
447+ case 0x6000:
448+ V[x] = (opcode & 0x00FF);
449+ pc += 2;
450+ printf("6xkk: The interpreter puts the value kk into register V[x] \n");
451+ break;
452+
453+ // 7xkk: ADD Vx, byte
454+ case 0x7000:
455+ V[x] += opcode & 0x00FF;
456+ pc += 2;
457+ printf("7xkk: Adds the value kk ot the value of V[x] then stores it in "
458+ "V[x] \n");
459+ break;
460+
461+ // 1NNN: Jumps to address NNN
462+ case 0x1000:
463+ printf("1nnn: Jump to location nnn \n");
464+ pc = opcode & 0x0FFF;
465+ break;
466+
467+ // Display n-byte sprite starting at memory location I at (Vx, Vy)
468+ // Set VF = collision.
469+ case 0xD000:
470+ draw_flag = 1;
471+ unsigned short height = opcode & 0x000F;
472+ unsigned short pixel;
473+ // set collision flag to 0
474+ V[0xF] = 0;
475+ // loop over each row
476+ for (int row = 0; row < height; row++) {
477+ // fetch the pixel value from the memory starting at location I
478+ pixel = memory[I + row];
479+ // loop over 8 bits of one row
480+ for (int col = 0; col < 10; col++) {
481+ // check if current evaluated pixel is set to 1 (0x80 >>
482+ // col scnas throught the byte, one bit at the time)
483+ if ((pixel & (0x80 >> col)) != 0) {
484+ // if drawing causes any pixel to be erased set the
485+ // collision flag to 1
486+ if (gfx[(V[x] + col + ((V[y] + row) * 64))] == 1) {
487+ V[0xF] = 1;
488+ }
489+ // set pixel value by using XOR
490+ gfx[V[x] + col + ((V[y] + row) * 64)] ^= 1;
491+ }
492+ }
493+ }
494+ printf(
495+ "Dxyn: Display n-byte sprite starting at memory location I at (Vx, "
496+ "Vy), set VF to collision \n");
497+ pc += 2;
498+ break;
499+
500+ // Instructions starting with FX
501+ case 0xF000:
502+ switch (opcode & 0x00FF) {
503+ case 0x0007:
504+ printf("Fx07: Place value of delay_timer into V[x]\n");
505+ V[x] = delay_timer;
506+ pc += 2;
507+ break;
508+
509+ case 0x000A:
510+ printf(
511+ "Fx0A: Stop all execution till key press, keypress is stored in "
512+ "V[x]\n");
513+ for (int i = 0; i < 16; i++) {
514+ if (keypad[i]) {
515+ V[x] = i;
516+ pc += 2;
517+ break;
518+ }
519+ }
520+ break;
521+
522+ case 0x0015:
523+ printf("Fx15: Sets the delay_timer value to V[x]\n");
524+ delay_timer = V[x];
525+ pc += 2;
526+ break;
527+
528+ // FX18: Sets the sound timer to Vx
529+ case 0x0018:
530+ printf("Fx18: Sets the sound_timer value to V[x]\n");
531+ sound_timer = V[x];
532+ pc += 2;
533+ break;
534+
535+ // FX1E: Adds Vx to I
536+ case 0x001E:
537+ printf("Fx1E:The values of I and Vx are added, and the results are "
538+ "stored in I\n");
539+ I += V[x];
540+ pc += 2;
541+ break;
542+
543+ // FX29: Sets I to the location of the sprite for the character
544+ // in Vx
545+ case 0x0029:
546+ printf("Fx29: Set location of I to mathching 0x sprite in V[x] \n");
547+ // Each digit contains 5 bytes
548+ I = V[x] * 5;
549+ pc += 2;
550+ break;
551+
552+ /*
553+ * FX33:
554+ *
555+ * Stores the binary-coded decimal representation
556+ * of VX, with the most significant of three digits
557+ * at the address in I, the middle digit at I plus
558+ * 1, and the least significant digit at I plus 2.
559+ * (In other words, take the decimal representation
560+ * of VX, place the hundreds digit in memory
561+ * at location in I, the tens digit at
562+ * location I+1, and the ones digit at
563+ * location I+2.)
564+ * */
565+
566+ case 0x0033:
567+ printf(
568+ "Fx33: Stores the binary-coded decimal representation of VX \n");
569+ memory[I] = (V[x] % 1000) / 100;
570+ memory[I + 1] = (V[x] % 100) / 10;
571+ memory[I + 2] = (V[x] % 10);
572+
573+ pc += 2;
574+ break;
575+
576+ case 0x0055:
577+ printf("Fx55: Stores V[0] to V[x] in memory starting at I\n");
578+
579+ for (int i = 0; i <= x; i++) {
580+ V[i] = memory[I + i];
581+ }
582+
583+ pc += 2;
584+ break;
585+
586+ // Fills V0 through Vx (Vx included) with values from memory
587+ // starting at addr I.
588+ case 0x0065:
589+ printf("Read registers V0 through Vx from memory starting at "
590+ "location I \n");
591+ for (int i = 0; i <= x; i++) {
592+ V[i] = memory[I + i];
593+ }
594+ pc += 2;
595+ break;
596+
597+ default:
598+ printf("Unknown opcode 0x%x.\n", opcode);
599+ break;
600+ }
601+ break;
602+
603+ // Instructions starting with 8
604+ case (0x8000):
605+ switch (opcode & 0x0FFF) {
606+ // 8xy0: Sets Vx to Vy
607+ case (0x0000):
608+ V[x] = V[y];
609+ pc += 2;
610+ break;
611+
612+ // 8xy1: V[x] = V[x] | V[y]
613+ case (0x0001):
614+ V[x] = (V[x] | V[y]);
615+ pc += 2;
616+ break;
617+
618+ // 8xy2: V[x] = V[x] | V[y]
619+ case (0x0002):
620+ V[x] = (V[x] & V[y]);
621+ pc += 2;
622+ break;
623+
624+ // 8xy3: V[x] = [Vx] ^ V[y]
625+ case (0x0003):
626+ V[x] = (V[x] ^ V[y]);
627+ pc += 2;
628+ break;
629+
630+ // 8xy4: V[x] = V[x] + V[y], set VF = carry.
631+ case (0x0004):
632+ if (V[x] + V[y] > 255) {
633+ printf("is this valid?");
634+ V[0xF] = 1;
635+ } else {
636+ V[0xF] = 0;
637+ }
638+ V[x] += V[y];
639+ pc += 2;
640+ break;
641+
642+ // 8xy5: V[x] = V[x] - V[y], set VF = NOT BORROW
643+ case (0x0005):
644+ if (V[x] > V[y]) {
645+ V[0xF] = 1;
646+ } else {
647+ V[0xF] = 0;
648+ }
649+ V[x] -= V[y];
650+ pc += 2;
651+ break;
652+
653+ // 8xy6: Sets Vx to Vy minus Vx. Vf is set to 0 when there's a borrow
654+ case (0x0006):
655+ V[0xF] = V[x] & 0x1;
656+ V[x] = (V[x] >> 1);
657+ pc += 2;
658+ break;
659+
660+ // Set Vx = Vy - Vx, set VF = NOT borrow
661+ case (0x0007):
662+ if (V[y] > V[x]) {
663+ V[0xF] = 1;
664+ } else {
665+ V[0xF] = 0;
666+ }
667+ V[x] = V[y] - V[x];
668+ pc += 2;
669+ break;
670+
671+ default:
672+ printf("Unknown opcode 0x%X.\n", opcode);
673+ break;
674+ }
675+ break;
676+
677+ default:
678+ printf("Unknown opcode 0x%X.\n", opcode);
679 }
680- printf("Dxyn: Display n-byte sprite starting at memory location I at (Vx, Vy), set VF to collision \n");
681- pc += 2;
682- break;
683-
684- default:
685- printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
686- printf("OpCode after opcode & 0xF000: 0x%X \n", opcode & 0xF000);
687- }
688-
689- // Update timers
690- if (delay_timer > 0)
691- --delay_timer;
692- if (sound_timer > 0) {
693- if (sound_timer == 1)
694- printf("BEEP!\n");
695- --sound_timer;
696- }
697-}
698
699-int main(int argc, char *argv[]) {
700- chip8_initialize();
701- chip8_load_program(argv[1]);
702- chip8_init_display();
703- /* while (1) {} */
704+ // Update timers
705+ if (delay_timer > 0)
706+ --delay_timer;
707+ if (sound_timer > 0) {
708+ if (sound_timer == 1)
709+ printf("BEEP!\n");
710+ --sound_timer;
711+ }
712+}
713
714- for (int i = 0; i < 50; i++) {
715- chip8_emulate_cycle();
716- if (draw_flag == 1) {
717- chip8_draw(gfx);
718+int main(int argc, char* argv[])
719+{
720+ chip8_initialize();
721+ chip8_load_program(argv[1]);
722+ chip8_init_display();
723+ /* while (1) {} */
724+
725+ for (int i = 0; i < 500; i++) {
726+ chip8_emulate_cycle();
727+ if (draw_flag == 1) {
728+ chip8_draw(gfx);
729+ }
730+ usleep(10000);
731 }
732- usleep(150000);
733- }
734- SDL_DestroyWindow(window);
735- SDL_Quit();
736- return 0;
737+ SDL_DestroyWindow(window);
738+ SDL_Quit();
739+ return 0;
740 }