PancakeNESEmu
A homebrewed NES Emulator written in C
Loading...
Searching...
No Matches
cpu.c
Go to the documentation of this file.
1#include "core/cpu.h"
2#include "core/opcodes.h"
3#include "core/types.h"
4#include "macros.h"
5
6#include <stdio.h>
7#include <stdlib.h>
8
9void init_cpu(CPU* cpu, memory mem) {
10 cpu->program_counter = 0xFFFC;
11 cpu->stack_pointer = 0xFF;
12 cpu->accumulator = 0x00;
13 cpu->register_x = 0x00;
14 cpu->register_y = 0x00;
15 cpu->flags = 0x00;
16 cpu->mem = mem;
17 cpu->cache = 0x00;
18 cpu->cycle_counter = 0x00;
19}
20
21void free_cpu(CPU* cpu) {
22 free_memory(cpu->mem);
23 free(cpu);
24 cpu = ((void*)0);
25}
26
27void start_cpu(CPU* cpu) {
28 init_cpu(cpu, cpu->mem);
29 cpu->program_counter = get_address(cpu);
30}
31
32unsigned char get_next_instruction(CPU* cpu) {
33
34 switch (cpu->mem[cpu->program_counter]) {
35
36 case ADC_A:
37
38 case ADC_AX:
39
40 case ADC_AY:
41
42 case AND_A:
43
44 case AND_AX:
45
46 case AND_AY:
47
48 case ASL_A:
49
50 case ASL_AX:
51
52 case BIT_A:
53
54 case CMP_A:
55
56 case CMP_AX:
57
58 case CMP_AY:
59
60 case CPX_A:
61
62 case CPY_A:
63
64 case DEC_A:
65
66 case DEC_AX:
67
68 case EOR_A:
69
70 case EOR_AX:
71
72 case EOR_AY:
73
74 case INC_A:
75
76 case INC_AX:
77
78 case JMP_A:
79
80 case JMP_Id:
81
82 case JSR:
83
84 case LDA_A:
85
86 case LDA_AX:
87
88 case LDA_AY:
89
90 case LDX_A:
91
92 case LDX_AY:
93
94 case LDY_A:
95
96 case LDY_AX:
97
98 case LSR_A:
99
100 case LSR_AX:
101
102 case ORA_A:
103
104 case ORA_AX:
105
106 case ORA_AY:
107
108 case ROL_A:
109
110 case ROL_AX:
111
112 case ROR_A:
113
114 case ROR_AX:
115
116 case SBC_A:
117
118 case SBC_AX:
119
120 case SBC_AY:
121
122 case STA_A:
123
124 case STA_AX:
125
126 case STA_AY:
127
128 case STX_A:
129
130 case STY_A:
131 cpu->program_counter += 3;
132 break;
133
134 case BRK:
135
136 case CLC:
137
138 case CLD:
139
140 case CLI:
141
142 case CLV:
143
144 case DEX:
145
146 case DEY:
147
148 case INX:
149
150 case INY:
151
152 case LSR_Ac:
153
154 case NOP:
155
156 case PHP:
157
158 case PHA:
159
160 case PLP:
161
162 case PLA:
163
164 case ROR_Ac:
165
166 case ROL_Ac:
167
168 case RTI:
169
170 case RTS:
171
172 case SEC:
173
174 case SED:
175
176 case SEI:
177
178 case TAX:
179
180 case TXA:
181
182 case TAY:
183
184 case TYA:
185
186 case TSX:
187
188 case TXS:
189 cpu->program_counter += 1;
190 break;
191
192 default:
193 cpu->program_counter += 2;
194 break;
195 }
196
197 unsigned char cycles = 0;
198
199 switch (cpu->mem[cpu->program_counter]) {
200
201 case TAX:
202
203 case TAY:
204
205 case TSX:
206
207 case TXA:
208
209 case TXS:
210
211 case TYA:
212
213 case SEC:
214
215 case SED:
216
217 case SEI:
218
219 case SBC_I:
220
221 case ROR_Ac:
222
223 case ROL_Ac:
224
225 case ORA_I:
226
227 case NOP:
228
229 case LSR_Ac:
230
231 case LDY_I:
232
233 case LDA_I:
234
235 case ASL_Ac:
236
237 case AND_I:
238
239 case LDX_I:
240
241 case CLD:
242
243 case CLI:
244
245 case CLV:
246
247 case CPX_I:
248
249 case CPY_I:
250
251 case CMP_I:
252
253 case DEX:
254
255 case DEY:
256
257 case EOR_I:
258
259 case INX:
260
261 case INY:
262
263 case ADC_I:
264 cycles = 2;
265 break;
266
267 case STX_Z:
268
269 case STA_Z:
270
271 case SBC_Z:
272
273 case PHA:
274
275 case PHP:
276
277 case ORA_Z:
278
279 case LDX_Z:
280
281 case LDA_Z:
282
283 case JMP_A:
284
285 case EOR_Z:
286
287 case CPY_Z:
288
289 case CPX_Z:
290
291 case CMP_Z:
292
293 case AND_Z:
294
295 case ADC_Z:
296
297 case LDY_Z:
298 cycles = 3;
299 break;
300
301 case STX_A:
302
303 case STX_ZY:
304
305 case STA_ZX:
306
307 case STA_A:
308
309 case SBC_ZX:
310
311 case SBC_A:
312
313 case PLA:
314
315 case PLP:
316
317 case LDY_ZX:
318
319 case LDY_A:
320
321 case LDA_ZX:
322
323 case LDA_A:
324
325 case EOR_ZX:
326
327 case EOR_A:
328
329 case CPY_A:
330
331 case CPX_A:
332
333 case CMP_ZX:
334
335 case CMP_A:
336
337 case LDX_ZY:
338
339 case LDX_A:
340
341 case AND_ZX:
342
343 case ADC_ZX:
344
345 case AND_A:
346
347 case ORA_ZX:
348
349 case ORA_A:
350
351 case ADC_A:
352 cycles = 4;
353 break;
354
355 case STA_AX:
356
357 case STA_AY:
358
359 case ROR_Z:
360
361 case ROL_Z:
362
363 case LSR_Z:
364
365 case JMP_Id:
366
367 case INC_Z:
368
369 case DEC_Z:
370
371 case ASL_Z:
372 cycles = 5;
373 break;
374
375 case SBC_AX:
376
377 case LDA_AX:
378
379 case EOR_AX:
380
381 case CMP_AX:
382
383 case AND_AX:
384
385 case LDY_AX:
386
387 case ORA_AX:
388
389 case ADC_AX:
390 if (is_page_crossed(get_address(cpu), cpu->register_x)) {
391 cycles = 5;
392 } else {
393 cycles = 4;
394 }
395 break;
396
397 case SBC_AY:
398
399 case ORA_AY:
400
401 case LDA_AY:
402
403 case EOR_AY:
404
405 case CMP_AY:
406
407 case AND_AY:
408
409 case LDX_AY:
410
411 case ADC_AY:
412 if (is_page_crossed(get_address(cpu), cpu->register_y)) {
413 cycles = 5;
414 } else {
415 cycles = 4;
416 }
417 break;
418
419 case RTI:
420
421 case RTS:
422
423 case ROR_ZX:
424
425 case ROR_A:
426
427 case ROL_ZX:
428
429 case ROL_A:
430
431 case LSR_ZX:
432
433 case LSR_A:
434
435 case LDA_IdX:
436
437 case JSR:
438
439 case INC_ZX:
440
441 case INC_A:
442
443 case EOR_IdX:
444
445 case DEC_ZX:
446
447 case DEC_A:
448
449 case CMP_IdX:
450
451 case ASL_ZX:
452
453 case ASL_A:
454
455 case AND_IdX:
456
457 case ORA_IdX:
458
459 case ADC_IdX:
460
461 case STA_IdX:
462
463 case STA_IdY:
464
465 case SBC_IdX:
466 cycles = 6;
467 break;
468
469 case LDA_IdY:
470
471 case EOR_IdY:
472
473 case AND_IdY:
474
475 case CMP_IdY:
476
477 case ORA_IdY:
478
479 case SBC_IdY:
480
481 case ADC_IdY:
482 if (is_page_crossed(indirect_indexed(cpu, cpu->program_counter + 1, 0), cpu->register_y)) {
483 cycles = 6;
484 } else {
485 cycles = 5;
486 }
487 break;
488
489 case ROL_AX:
490
491 case ROR_AX:
492
493 case LSR_AX:
494
495 case INC_AX:
496
497 case DEC_AX:
498
499 case BRK:
500
501 case ASL_AX:
502 cycles = 7;
503 break;
504
505 case BCC:
506 if (!GET_C_FLAG(cpu)) {
507 cycles = 1;
508 }
509
510 branch_page_test:
511 if (is_page_crossed(cpu->program_counter, cpu->mem[cpu->program_counter + 1])) {
512 cycles += 4;
513 } else {
514 cycles += 2;
515 }
516
517 break;
518
519 case BEQ:
520 if (GET_Z_FLAG(cpu)) {
521 cycles = 1;
522 }
523 goto branch_page_test;
524 break;
525
526 case BCS:
527 if (GET_C_FLAG(cpu)) {
528 cycles = 1;
529 }
530 goto branch_page_test;
531 break;
532
533 case BMI:
534 if (GET_N_FLAG(cpu)) {
535 cycles = 1;
536 }
537 goto branch_page_test;
538 break;
539
540 case BNE:
541 if (!GET_Z_FLAG(cpu)) {
542 cycles = 1;
543 }
544 goto branch_page_test;
545 break;
546
547 case BPL:
548 if (!GET_N_FLAG(cpu)) {
549 cycles = 1;
550 }
551 goto branch_page_test;
552 break;
553
554 case BVC:
555 if (!GET_V_FLAG(cpu)) {
556 cycles = 1;
557 }
558 goto branch_page_test;
559 break;
560
561 case BVS:
562 if (GET_V_FLAG(cpu)) {
563 cycles = 1;
564 }
565 goto branch_page_test;
566 break;
567
568 default:
569 cycles = 0;
570 }
571
572 return cycles;
573}
574
576
577 switch (cpu->mem[cpu->program_counter]) {
578
579 case ADC_I:
580 ADD_immediate(cpu, cpu->mem[cpu->program_counter + 1]);
581 break;
582
583 case ADC_Z:
584 ADD_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
585 break;
586
587 case ADC_ZX:
588 ADD_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
589 break;
590
591 case ADC_A:
592 ADD_absolute(cpu, get_address(cpu));
593 break;
594
595 case ADC_AX:
596 ADD_offset(cpu, get_address(cpu), cpu->register_x);
597 break;
598
599 case ADC_AY:
600 ADD_offset(cpu, get_address(cpu), cpu->register_y);
601 break;
602
603 case ADC_IdX:
604 ADD_indexed_indirect(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
605 break;
606
607 case ADC_IdY:
608 ADD_indirect_indexed(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_y);
609 break;
610
611 case AND_I:
612 AND_immediate(cpu, cpu->mem[cpu->program_counter + 1]);
613 break;
614
615 case AND_Z:
616 AND_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
617 break;
618
619 case AND_ZX:
620 AND_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
621 break;
622
623 case AND_A:
624 AND_absolute(cpu, get_address(cpu));
625 break;
626
627 case AND_AX:
628 AND_offset(cpu, get_address(cpu), cpu->register_x);
629 break;
630
631 case AND_AY:
632 AND_offset(cpu, get_address(cpu), cpu->register_y);
633 break;
634
635 case AND_IdX:
636 AND_indexed_indirect(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
637 break;
638
639 case AND_IdY:
640 AND_indirect_indexed(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_y);
641 break;
642
643 case ASL_Ac:
644 SHIFT_LEFT_ACC(cpu);
645 break;
646
647 case ASL_Z:
648 SHIFT_LEFT_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
649 break;
650
651 case ASL_ZX:
652 SHIFT_LEFT_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
653 break;
654
655 case ASL_A:
657 break;
658
659 case ASL_AX:
661 break;
662
663 case BCC:
664 BRANCH_Carry_C(cpu, cpu->mem[cpu->program_counter + 1]);
665 break;
666
667 case BCS:
668 BRANCH_Carry_S(cpu, cpu->mem[cpu->program_counter + 1]);
669 break;
670
671 case BEQ:
672 BRANCH_Equal(cpu, cpu->mem[cpu->program_counter + 1]);
673 break;
674
675 case BIT_Z:
676 BIT_TEST(cpu, cpu->mem[cpu->program_counter + 1]);
677 break;
678
679 case BIT_A:
680 BIT_TEST(cpu, get_address(cpu));
681 break;
682
683 case BMI:
684 BRANCH_If_Minus(cpu, cpu->mem[cpu->program_counter + 1]);
685 break;
686
687 case BNE:
688 BRANCH_Not_Equal(cpu, cpu->mem[cpu->program_counter + 1]);
689 break;
690
691 case BPL:
692 BRANCH_If_Positive(cpu, cpu->mem[cpu->program_counter + 1]);
693 break;
694
695 case BRK:
696 BREAK(cpu);
697 break;
698
699 case BVC:
700 BRANCH_Overflow_C(cpu, cpu->mem[cpu->program_counter + 1]);
701 break;
702
703 case BVS:
704 BRANCH_Overflow_S(cpu, cpu->mem[cpu->program_counter + 1]);
705 break;
706
707 case CLC:
708 CLEAR_C_FLAG(cpu);
709 break;
710
711 case CLD:
712 CLEAR_D_FLAG(cpu);
713 break;
714
715 case CLI:
716 CLEAR_I_FLAG(cpu);
717 break;
718
719 case CLV:
720 CLEAR_V_FLAG(cpu);
721 break;
722
723 case CMP_I:
724 COMPARE_Immediate_ACC(cpu, cpu->mem[cpu->program_counter + 1]);
725 break;
726
727 case CMP_A:
729 break;
730
731 case CMP_AX:
733 break;
734
735 case CMP_AY:
737 break;
738
739 case CMP_IdX:
741 break;
742
743 case CMP_IdY:
745 break;
746
747 case CMP_Z:
748 COMPARE_absolute_ACC(cpu, cpu->mem[cpu->program_counter + 1]);
749 break;
750
751 case CMP_ZX:
752 COMPARE_offset_ACC(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
753 break;
754
755 case CPX_I:
756 COMPARE_Immediate_X(cpu, cpu->mem[cpu->program_counter + 1]);
757 break;
758
759 case CPX_Z:
760 COMPARE_absolute_X(cpu, cpu->mem[cpu->program_counter + 1]);
761 break;
762
763 case CPX_A:
765 break;
766
767 case CPY_I:
768 COMPARE_Immediate_Y(cpu, cpu->mem[cpu->program_counter + 1]);
769 break;
770
771 case CPY_Z:
772 COMPARE_absolute_Y(cpu, cpu->mem[cpu->program_counter + 1]);
773 break;
774
775 case CPY_A:
777 break;
778
779 case DEX:
780 DEC_X(cpu);
781 break;
782
783 case DEY:
784 DEC_Y(cpu);
785 break;
786
787 case DEC_Z:
788 DEC_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
789 break;
790
791 case DEC_A:
792 DEC_absolute(cpu, get_address(cpu));
793 break;
794
795 case DEC_ZX:
796 DEC_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
797 break;
798
799 case DEC_AX:
800 DEC_offset(cpu, get_address(cpu), cpu->register_x);
801 break;
802
803 case INC_Z:
804 INC_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
805 break;
806
807 case INC_A:
808 INC_absolute(cpu, get_address(cpu));
809 break;
810
811 case INC_ZX:
812 INC_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
813 break;
814
815 case INC_AX:
816 INC_offset(cpu, get_address(cpu), cpu->register_x);
817 break;
818
819 case INX:
820 INC_X(cpu);
821 break;
822
823 case INY:
824 INC_Y(cpu);
825 break;
826
827 case JMP_A:
828 JUMP_absolute(cpu, get_address(cpu));
829 break;
830
831 case JMP_Id:
832 JUMP_indirect(cpu, get_address(cpu));
833 break;
834
835 case EOR_I:
836 XOR_immediate(cpu, cpu->mem[cpu->program_counter + 1]);
837 break;
838
839 case EOR_Z:
840 XOR_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
841 break;
842
843 case EOR_ZX:
844 XOR_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
845 break;
846
847 case EOR_A:
848 XOR_absolute(cpu, get_address(cpu));
849 break;
850
851 case EOR_AX:
852 XOR_offset(cpu, get_address(cpu), cpu->register_x);
853 break;
854
855 case EOR_AY:
856 XOR_offset(cpu, get_address(cpu), cpu->register_y);
857 break;
858
859 case EOR_IdX:
861 break;
862
863 case EOR_IdY:
865 break;
866
867 case JSR:
868 JUMP_Subroutine(cpu, get_address(cpu));
869 break;
870
871 case LDA_I:
872 LD_immediate_ACC(cpu, cpu->mem[cpu->program_counter + 1]);
873 break;
874
875 case LDA_Z:
876 LD_absolute_ACC(cpu, cpu->mem[cpu->program_counter + 1]);
877 break;
878
879 case LDA_ZX:
880 LD_offset_ACC(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
881 break;
882
883 case LDA_A:
884 LD_absolute_ACC(cpu, get_address(cpu));
885 break;
886
887 case LDA_AX:
888 LD_offset_ACC(cpu, get_address(cpu), cpu->register_x);
889 break;
890
891 case LDA_AY:
892 LD_offset_ACC(cpu, get_address(cpu), cpu->register_y);
893 break;
894
895 case LDA_IdX:
897 break;
898
899 case LDA_IdY:
901 break;
902
903 case LDX_I:
904 LD_immediate_X(cpu, cpu->mem[cpu->program_counter + 1]);
905 break;
906
907 case LDX_Z:
908 LD_absolute_X(cpu, cpu->mem[cpu->program_counter + 1]);
909 break;
910
911 case LDX_ZY:
912 LD_offset_X(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_y);
913 break;
914
915 case LDX_A:
916 LD_absolute_X(cpu, get_address(cpu));
917 break;
918
919 case LDX_AY:
920 LD_offset_X(cpu, get_address(cpu), cpu->register_y);
921 break;
922
923 case LDY_I:
924 LD_immediate_Y(cpu, cpu->mem[cpu->program_counter + 1]);
925 break;
926
927 case LDY_Z:
928 LD_absolute_Y(cpu, cpu->mem[cpu->program_counter + 1]);
929 break;
930
931 case LDY_ZX:
932 LD_offset_Y(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_y);
933 break;
934
935 case LDY_A:
936 LD_absolute_Y(cpu, get_address(cpu));
937 break;
938
939 case LDY_AX:
940 LD_offset_Y(cpu, get_address(cpu), cpu->register_x);
941 break;
942
943 case LSR_Ac:
944 SHIFT_RIGHT_ACC(cpu);
945 break;
946
947 case LSR_Z:
948 SHIFT_RIGHT_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
949 break;
950
951 case LSR_ZX:
952 SHIFT_RIGHT_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
953 break;
954
955 case LSR_A:
957 break;
958
959 case LSR_AX:
961 break;
962
963 case NOP:
964 break;
965
966 case ORA_I:
967 OR_immediate(cpu, cpu->mem[cpu->program_counter + 1]);
968 break;
969
970 case ORA_Z:
971 OR_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
972 break;
973
974 case ORA_ZX:
975 OR_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
976 break;
977
978 case ORA_A:
979 OR_absolute(cpu, get_address(cpu));
980 break;
981
982 case ORA_AX:
983 OR_offset(cpu, get_address(cpu), cpu->register_x);
984 break;
985
986 case ORA_AY:
987 OR_offset(cpu, get_address(cpu), cpu->register_y);
988 break;
989
990 case ORA_IdX:
992 break;
993
994 case ORA_IdY:
996 break;
997
998 case PHA:
999 PUSH_ACC(cpu);
1000 break;
1001
1002 case PHP:
1003 PUSH_FLAGS(cpu);
1004 break;
1005
1006 case PLA:
1007 PULL_ACC(cpu);
1008 break;
1009
1010 case PLP:
1011 PULL_FLAGS(cpu);
1012 break;
1013
1014 case ROL_Ac:
1015 ROTATION_LEFT_ACC(cpu);
1016 break;
1017
1018 case ROL_Z:
1019 ROTATION_LEFT_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
1020 break;
1021
1022 case ROL_ZX:
1023 ROTATION_LEFT_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
1024 break;
1025
1026 case ROL_A:
1028 break;
1029
1030 case ROL_AX:
1032 break;
1033
1034 case ROR_Ac:
1035 ROTATION_RIGHT_ACC(cpu);
1036 break;
1037
1038 case ROR_Z:
1039 ROTATION_RIGHT_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
1040 break;
1041
1042 case ROR_ZX:
1043 ROTATION_RIGHT_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
1044 break;
1045
1046 case ROR_A:
1048 break;
1049
1050 case ROR_AX:
1052 break;
1053
1054 case RTI:
1055 RETURN_Interrupt(cpu);
1056 break;
1057
1058 case RTS:
1059 RETURN_Subroutine(cpu);
1060 break;
1061
1062 case SBC_I:
1063 SBC_immediate(cpu, cpu->mem[cpu->program_counter + 1]);
1064 break;
1065
1066 case SBC_Z:
1067 SBC_absolute(cpu, cpu->mem[cpu->program_counter + 1]);
1068 break;
1069
1070 case SBC_ZX:
1071 SBC_offset(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
1072 break;
1073
1074 case SBC_A:
1075 SBC_absolute(cpu, get_address(cpu));
1076 break;
1077
1078 case SBC_AX:
1079 SBC_offset(cpu, get_address(cpu), cpu->register_x);
1080 break;
1081
1082 case SBC_AY:
1083 SBC_offset(cpu, get_address(cpu), cpu->register_y);
1084 break;
1085
1086 case SBC_IdX:
1088 break;
1089
1090 case SBC_IdY:
1092 break;
1093
1094 case SEC:
1095 SET_C_FLAG(cpu);
1096 break;
1097
1098 case SED:
1099 SET_D_FLAG(cpu);
1100 break;
1101
1102 case SEI:
1103 SET_I_FLAG(cpu);
1104 break;
1105
1106 case STA_Z:
1107 STR_absolute_ACC(cpu, cpu->mem[cpu->program_counter + 1]);
1108 break;
1109
1110 case STA_ZX:
1111 STR_offset_ACC(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
1112 break;
1113
1114 case STA_A:
1115 STR_absolute_ACC(cpu, get_address(cpu));
1116 break;
1117
1118 case STA_AX:
1119 STR_offset_ACC(cpu, get_address(cpu), cpu->register_x);
1120 break;
1121
1122 case STA_AY:
1123 STR_offset_ACC(cpu, get_address(cpu), cpu->register_y);
1124 break;
1125
1126 case STA_IdX:
1128 break;
1129
1130 case STA_IdY:
1132 break;
1133
1134 case STX_Z:
1135 STR_absolute_X(cpu, cpu->mem[cpu->program_counter + 1]);
1136 break;
1137
1138 case STX_ZY:
1139 STR_offset_X(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_y);
1140 break;
1141
1142 case STX_A:
1143 STR_absolute_X(cpu, get_address(cpu));
1144 break;
1145
1146 case STY_Z:
1147 STR_absolute_Y(cpu, cpu->mem[cpu->program_counter + 1]);
1148 break;
1149
1150 case STY_ZX:
1151 STR_offset_Y(cpu, cpu->mem[cpu->program_counter + 1], cpu->register_x);
1152 break;
1153
1154 case STY_A:
1155 STR_absolute_Y(cpu, get_address(cpu));
1156 break;
1157
1158 case TAX:
1159 TR_ACC_X(cpu);
1160 break;
1161
1162 case TSX:
1163 TR_SP_X(cpu);
1164 break;
1165
1166 case TXA:
1167 TR_X_ACC(cpu);
1168 break;
1169
1170 case TYA:
1171 TR_Y_ACC(cpu);
1172 break;
1173
1174 case TAY:
1175 TR_ACC_Y(cpu);
1176 break;
1177
1178 case TXS:
1179 TR_X_SP(cpu);
1180 break;
1181
1182 default:
1183 return ERR_ABN_OPCODE;
1184 break;
1185 }
1186
1187 return 0;
1188}
1189
1191 if (cpu->cycle_counter == 0) {
1192 if (execute_instruction(cpu)) {
1193 goto error;
1194 };
1196
1197 if (cpu->cycle_counter == 0) {
1198 error:
1199 printf("Abnormal opcode: %#02x\n", cpu->mem[cpu->program_counter]);
1200 return ERR_ABN_OPCODE;
1201 }
1202 memory_mirroring(cpu->mem);
1203 return 0;
1204 }
1205
1206 --(cpu->cycle_counter);
1207 return 0;
1208}
1209
1210void print_cpu_state(CPU* processor) {
1211
1212 printf("|======== Registers State ========|\n");
1213 printf("Accumulator: %i\n", processor->accumulator);
1214 printf("X Register: %i\n", processor->register_x);
1215 printf("Y Register: %i\n", processor->register_y);
1216 printf("Program Counter: %#04x\n", processor->program_counter);
1217 printf("Stack Pointer: %#02x\n", processor->stack_pointer);
1218 printf("Flags: %#02x\n", processor->flags);
1219
1220 printf("\n");
1221
1222 printf("|======== Flags State ========|\n");
1223 printf("Negative Flag (N): %i\n", (GET_N_FLAG(processor) >> 7));
1224 printf("Overflow Flag (V): %i\n", (GET_V_FLAG(processor) >> 6));
1225 printf("Pause Flag (P): %i\n", (GET_P_FLAG(processor) >> 5));
1226 printf("Break Flag (B): %i\n", (GET_B_FLAG(processor) >> 4));
1227 printf("Decimal Flag (D): %i\n", (GET_D_FLAG(processor) >> 3));
1228 printf("Interrupt Flag (I): %i\n", (GET_I_FLAG(processor) >> 2));
1229 printf("Zero Flag (Z): %i\n", (GET_Z_FLAG(processor) >> 1));
1230 printf("Carry Flag (C): %i\n", GET_C_FLAG(processor));
1231
1232 printf("\n");
1233}
1234
1235void print_cpu_expected(data acc, data x, data y, data flags, address pc, data sp) {
1236 printf("|======== EXPECTED: Registers State ========|\n");
1237 printf("Accumulator: %i\n", acc);
1238 printf("X Register: %i\n", x);
1239 printf("Y Register: %i\n", y);
1240 printf("Program Counter: %#04x\n", pc);
1241 printf("Stack Pointer: %#02x\n", sp);
1242 printf("Flags: %#02x\n", flags);
1243
1244 printf("\n");
1245
1246 printf("|======== EXPECTED: Flags State ========|\n");
1247 printf("Negative Flag (N): %i\n", ((flags & BIT_7_MASK) >> 7));
1248 printf("Overflow Flag (V): %i\n", ((flags & BIT_6_MASK) >> 6));
1249 printf("Pause Flag (P): %i\n", ((flags & BIT_5_MASK) >> 5));
1250 printf("Break Flag (B): %i\n", ((flags & BIT_4_MASK) >> 4));
1251 printf("Decimal Flag (D): %i\n", ((flags & BIT_3_MASK) >> 3));
1252 printf("Interrupt Flag (I): %i\n", ((flags & BIT_2_MASK) >> 2));
1253 printf("Zero Flag (Z): %i\n", ((flags & BIT_1_MASK) >> 1));
1254 printf("Carry Flag (C): %i\n", (flags & BIT_0_MASK));
1255
1256 printf("\n");
1257}
1258
1260
1261 printf("<====== Stack State =====>\n");
1262 printf("Stack pointer: %#02x\n", cpu->stack_pointer);
1263
1264 if (cpu->stack_pointer == 0xFF) {
1265 printf("\n");
1266 return;
1267 }
1268
1269 printf("sp: | int |\t | hex |\n\n");
1270
1271 for (uint8_t sp = cpu->stack_pointer + 1; sp < 0xFF; ++sp) {
1272 printf("%#02x: | %i |", sp, cpu->mem[STACK_END | sp]);
1273 printf("\t | %#02x |\n", cpu->mem[STACK_END | sp]);
1274 }
1275
1276 printf("%#02x: | %i |", 0xFF, cpu->mem[STACK_START]);
1277 printf("\t | %#02x |\n", cpu->mem[STACK_START]);
1278
1279 printf("\n");
1280}
1281
1283 printf("<===== EXPECTED: Stack State =====>\n");
1284 printf("Stack pointer: %#02x\n", start);
1285
1286 if (start == 0xFF) {
1287 printf("\n");
1288 return;
1289 }
1290
1291 printf("sp: | int |\t | hex |\n\n");
1292
1293 for (data sp = start + 1; sp < 0xFF; ++sp) {
1294 printf("%#02x: | %i |", sp, stack[sp]);
1295 printf("\t | %#02x |\n", stack[sp]);
1296 }
1297
1298 printf("%#02x: | %i |", 0xFF, stack[0xFF]);
1299 printf("\t | %#02x |\n", stack[0xFF]);
1300
1301 printf("\n");
1302}
1303
1304// The routine to implement when implementing hte reset
1305/*
1306Reset:
1307 sei ; disables all interr:upts of the NES
1308 cld ; disable decimal mode, the NES doesn't actually support the decimal mode when doing
1309calculation
1310
1311
1312 ; disable the IRQ (Interrupt Request) from the APU
1313 ; basically, we're preventing strange sound to play on startup
1314 ldx #$40
1315 stx APU_FRAMEC
1316
1317
1318 ; Initialize the Stack register
1319 ldx #$FF ; the Stack pointer offset starts at the last address possible
1320 txs ; we're transfering the offset to the correct register
1321
1322 inx ; we're doing that to reset the value in the X register. In a 8bit architecture,
1323doing #$FF + 1 = #$00
1324
1325
1326 ; Zero out the PPU registers
1327
1328 stx PPU_CTRL
1329 stx PPU_MASK
1330
1331
1332 ; Zero out the DMC_CTRL Register
1333 ; Prevent weird sounds from appearing randomly on startup
1334
1335 stx DMC_CTRL
1336
1337
1338 ; We have to wait for the first vBlank. Which means that the PPU has correctly start
1339
1340:
1341 bit PPU_STATUS ; bit op code tells us is the signed bit is set to 1 or 0. | If set to 1,
1342then this is a negative bit, so BPL (Branch if PLus/Positive) will not branch. bpl :- ;
1343branch back to the previous anonymous label if the PPU is not drawing a vBlank.
1344
1345 txa ; transfer x value to the acc. Here: Zero out the Acc
1346*/
errcode_t step_cpu(CPU *cpu)
Function that step a clock cycle.
Definition cpu.c:1190
void print_stack_expected(memory stack, data start)
Procedure that display the expected state of the stack.
Definition cpu.c:1282
unsigned char get_next_instruction(CPU *cpu)
Function that get the next instruction written in the ROM.
Definition cpu.c:32
void init_cpu(CPU *cpu, memory mem)
Procedure that initialize the CPU to its boot/reset state.
Definition cpu.c:9
void print_cpu_state(CPU *processor)
Procedure that displays the current state of the CPU.
Definition cpu.c:1210
void print_cpu_expected(data acc, data x, data y, data flags, address pc, data sp)
Procedure that display the expected state of the CPU.
Definition cpu.c:1235
void print_stack_state(CPU *cpu)
Procedure that display the current state of the stack.
Definition cpu.c:1259
errcode_t execute_instruction(CPU *cpu)
Function that execute the current instruction in the ROM.
Definition cpu.c:575
void start_cpu(CPU *cpu)
Procedure that acts like the reset button of the NES.
Definition cpu.c:27
void free_cpu(CPU *cpu)
Procedure that free the memory used by the CPU and the memory array.
Definition cpu.c:21
#define ADD_indexed_indirect(processor, addr, offset)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mod...
Definition cpu.h:710
#define STR_absolute_X(processor, addr)
Procedure that store the X register value to a memory address.
Definition cpu.h:464
#define GET_V_FLAG(x)
Definition cpu.h:125
#define COMPARE_indexed_indirect_ACC(processor, addr, offset)
Procedure that performs a CMP operation (Z, C, N = A - M) with an indexed indirect addressing mode.
Definition cpu.h:1358
#define COMPARE_Immediate_ACC(processor, value)
Procedure that performs a CMP operation (Z,C,N = A - M) with an immediate value.
Definition cpu.h:1332
#define TR_ACC_X(processor)
Procedure that store the value in the accumulator in the X register.
Definition cpu.h:545
#define OR_indexed_indirect(processor, addr, offset)
Procedure that perform a OR with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mode...
Definition cpu.h:817
#define PULL_FLAGS(processor)
Procedure that pop the top value of the stack and return it to the flags register.
Definition cpu.h:642
#define COMPARE_absolute_Y(processor, addr)
Procedure that performs a CMP operation (Z, C, N = Y - M) with an indirect indexed addressing mode.
Definition cpu.h:1403
#define OR_absolute(processor, addr)
Procedure that performs a bitwise logic OR (A,Z,N = A&M) using absolute addressing mode.
Definition cpu.h:800
#define BRANCH_If_Minus(processor, offset)
Procedure that performs a BMI (branch if positive, if the N flag is clear)
Definition cpu.h:1025
#define AND_indirect_indexed(processor, addr, offset)
Procedure that perform a AND with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
Definition cpu.h:781
#define SET_D_FLAG(x)
Definition cpu.h:131
#define TR_ACC_Y(processor)
Procedure that store the value in accumulator in the Y register.
Definition cpu.h:551
#define ROTATION_RIGHT_absolute(processor, addr)
Procedure that performs a bit shift with rotation to the right (ROR operation) at the memory address ...
Definition cpu.h:1176
#define ROTATION_RIGHT_offset(processor, addr, offset)
Procedure that performs a bit shift with rotation to the right (ROR operation) at the memory address ...
Definition cpu.h:1198
#define GET_C_FLAG(x)
Definition cpu.h:119
#define ADD_immediate(processor, data)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+data+C) with an immediate.
Definition cpu.h:662
#define SHIFT_RIGHT_absolute(processor, addr)
Procedure that performs a bitshift to the right (LSR operation) at the address addr and place the 0th...
Definition cpu.h:1098
#define ROTATION_RIGHT_ACC(processor)
Procedure that performs a bit shift with rotation to the right (ROR operation) on the accumulator....
Definition cpu.h:1157
#define TR_X_SP(processor)
Procedure that store the value in the X register in the stack pointer.
Definition cpu.h:575
#define STR_offset_ACC(processor, addr, offset)
Procedure that store the accumulator value to a memory address + offset.
Definition cpu.h:488
#define XOR_immediate(processor, data)
Procedure that performs a bitwise logic XOR (A,Z,N = A & data)
Definition cpu.h:834
#define DEC_Y(processor)
Procedure that decrements the Y register.
Definition cpu.h:424
#define XOR_indexed_indirect(processor, addr, offset)
Procedure that perform a XOR with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mod...
Definition cpu.h:862
#define get_address(cpu)
Macro to recreate the current address pointed by pc + 1.
Definition cpu.h:180
#define STR_offset_X(processor, addr, offset)
Procedure that store the X register value to a memory address + offset.
Definition cpu.h:497
#define DEC_offset(processor, addr, offset)
Procedure that decrement a specific memory location.
Definition cpu.h:392
#define STR_absolute_ACC(processor, addr)
Procedure that store the accumulator value to a memory address.
Definition cpu.h:457
#define LD_indirect_indexed_ACC(processor, addr, offset)
Procedure that loads to the accmulator using Inderect Indexed.
Definition cpu.h:441
#define GET_N_FLAG(x)
Definition cpu.h:126
#define SET_I_FLAG(x)
Definition cpu.h:130
#define COMPARE_indirect_indexed_ACC(processor, addr, offset)
Procedure that performs a CMP operation (Z, C, N = A - M) with an indirect indexed addressing mode.
Definition cpu.h:1368
#define OR_immediate(processor, data)
Procedure that performs a bitwise logic OR (A,Z,N = A & data)
Definition cpu.h:789
#define ADD_indirect_indexed(processor, addr, offset)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
Definition cpu.h:719
#define is_page_crossed(addr, offset)
Macro to know if we cross a page when doing the instruction.
Definition cpu.h:189
#define AND_absolute(processor, addr)
Procedure that performs a bitwise logic AND (A,Z,N = A&M) using absolute addressing mode.
Definition cpu.h:755
#define BRANCH_Carry_S(processor, offset)
Procedure that performs a BCS (branch if positive, if the N flag is clear)
Definition cpu.h:1046
#define AND_indexed_indirect(processor, addr, offset)
Procedure that perform a AND with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mod...
Definition cpu.h:772
#define SET_C_FLAG(x)
Definition cpu.h:128
#define COMPARE_Immediate_X(processor, value)
Procedure that performs a CMP operation (Z, C, N = X - M) with a value addressing mode.
Definition cpu.h:1377
#define BRANCH_Not_Equal(processor, offset)
Procedure that performs a BNE (if the Z flag is clear)
Definition cpu.h:1011
#define BRANCH_If_Positive(processor, offset)
Procedure that performs a BPL (branch if positive, if the N flag is clear)
Definition cpu.h:997
#define STR_indirect_indexed_ACC(processor, addr, offset)
Procedure that store the accumulator value to a memory address using indirect indexed addressing mode...
Definition cpu.h:516
#define CLEAR_D_FLAG(x)
Definition cpu.h:142
#define INC_offset(processor, addr, offset)
Procedure that increment a specific memory location.
Definition cpu.h:400
#define COMPARE_offset_ACC(processor, addr, offset)
Procedure that performs a CMP operation (Z, C, N = A - M) with an absolute + offset addressing mode.
Definition cpu.h:1349
#define STR_offset_Y(processor, addr, offset)
Procedure that store the Y register value to a memory address + offset.
Definition cpu.h:506
#define DEC_X(processor)
Procedure that decrements the X register.
Definition cpu.h:418
#define BREAK(processor)
Procedure that performs a break instruction (forces an interrupt).
Definition cpu.h:1232
#define RETURN_Subroutine(processor)
Procedure that performs a return from subroutine (RTS instruction) by pulling the top two elements of...
Definition cpu.h:1287
#define LD_absolute_X(processor, addr)
Procedure that loads a value from memory at the address addr to the X register.
Definition cpu.h:310
#define LD_immediate_ACC(processor, d)
Procedure that loads an immediate (const value) in the accumulator.
Definition cpu.h:237
#define LD_immediate_X(processor, d)
Procedure that loads an immediate (const value) in the X register.
Definition cpu.h:244
#define SHIFT_LEFT_ACC(processor)
Procedure that performs a bitshift to the left (ASL operation) on the accumulator and place the 7th b...
Definition cpu.h:1076
#define BIT_TEST(processor, addr)
Procedure that performs a BIT test (A & M, N = M7, V = M6)
Definition cpu.h:951
#define ADD_offset(processor, addr, offset)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with absolute+offset addressing addr...
Definition cpu.h:701
#define PUSH_ACC(processor)
Procedure that push the accumulator value to the top of the stack.
Definition cpu.h:603
#define SHIFT_LEFT_absolute(processor, addr)
Procedure that performs a bitshift to the left (ASL operation) at the address addr and place the 7th ...
Definition cpu.h:1091
#define SBC_indexed_indirect(processor, addr, offset)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with indexed indirect addressing mod...
Definition cpu.h:928
#define INC_Y(processor)
Procedure that increments the Y register.
Definition cpu.h:412
#define XOR_absolute(processor, addr)
Procedure that performs a bitwise logic XOR (A,Z,N = A&M) using absolute addressing mode.
Definition cpu.h:845
#define LD_absolute_Y(processor, addr)
Procedure that loads a value from memory at the address addr to the Y register.
Definition cpu.h:317
#define JUMP_absolute(processor, addr)
Procedure that sets the program counter to a certain address (JMP instruction)
Definition cpu.h:1206
#define PULL_ACC(processor)
Procedure that pop the top value of the stack and return it to the accumulator.
Definition cpu.h:636
#define GET_P_FLAG(x)
Definition cpu.h:124
#define SBC_offset(processor, addr, offset)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with offset addressing mode.
Definition cpu.h:919
#define GET_B_FLAG(x)
Definition cpu.h:123
#define SBC_absolute(processor, addr)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with absolute addressing mode.
Definition cpu.h:910
#define OR_offset(processor, addr, offset)
Procedure that performs a bitwise logic OR (A,Z,N = A&M) using offset addressing mode.
Definition cpu.h:808
#define CLEAR_C_FLAG(x)
Definition cpu.h:139
#define SBC_immediate(processor, data)
Procedure that perform a substract with the carry flag (A,Z,C,N=A-data-C) with an immediate.
Definition cpu.h:880
#define BRANCH_Equal(processor, offset)
Procedure that performs a BEQ (branch if positive, if the N flag is clear)
Definition cpu.h:1039
#define TR_SP_X(processor)
Procedure that store the stack pointer in the X register.
Definition cpu.h:569
#define LD_indexed_indirect_ACC(processor, addr, offset)
Procedure that loads to the accumulator using Indexed Indirect.
Definition cpu.h:432
#define LD_offset_ACC(processor, addr, offset)
Procedure that loads a value from memory at address addr+offset to the X register.
Definition cpu.h:269
#define RETURN_Interrupt(processor)
Procedure that performs a return from interrupt (RTI instruction) by pulling the flags from the top o...
Definition cpu.h:1298
#define LD_absolute_ACC(processor, addr)
Procedure that loads a value from memory at the address addr to the accumulator.
Definition cpu.h:303
#define COMPARE_Immediate_Y(processor, value)
Procedure that performs a CMP operation (Z, C, N = Y - M) with a value addressing mode.
Definition cpu.h:1394
#define GET_Z_FLAG(x)
Definition cpu.h:120
#define indirect_indexed(cpu, addr, offset)
Macro to access memory by indirect indexed addressing mode.
Definition cpu.h:165
#define DEC_absolute(processor, addr)
Procedure that decrement a specific memory location.
Definition cpu.h:377
#define XOR_offset(processor, addr, offset)
Procedure that performs a bitwise logic XOR (A,Z,N = A&M) using offset addressing mode.
Definition cpu.h:853
#define CLEAR_I_FLAG(x)
Definition cpu.h:141
#define INC_absolute(processor, addr)
Procedure that increment a specific memory location.
Definition cpu.h:384
#define AND_offset(processor, addr, offset)
Procedure that performs a bitwise logic AND (A,Z,N = A&M) using offset addressing mode.
Definition cpu.h:763
#define TR_X_ACC(processor)
Procedure that store the value in the X register in the accumulator.
Definition cpu.h:557
#define SHIFT_RIGHT_ACC(processor)
Procedure that performs a bitshift to the right (LSR operation) on the accumulator and place the 0th ...
Definition cpu.h:1083
#define OR_indirect_indexed(processor, addr, offset)
Procedure that perform a OR with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
Definition cpu.h:826
#define XOR_indirect_indexed(processor, addr, offset)
Procedure that perform a XOR with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
Definition cpu.h:871
#define CLEAR_V_FLAG(x)
Definition cpu.h:145
#define ROTATION_LEFT_offset(processor, addr, offset)
Procedure that performs a bit shift with rotation to the left (ROL operation) at the memory address (...
Definition cpu.h:1187
#define GET_I_FLAG(x)
Definition cpu.h:121
#define TR_Y_ACC(processor)
Procedure that store the value in the Y register in the accumulator.
Definition cpu.h:563
#define COMPARE_absolute_X(processor, addr)
Procedure that performs a CMP operation (Z, C, N = X - M) with an indirect indexed addressing mode.
Definition cpu.h:1386
#define SBC_indirect_indexed(processor, addr, offset)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with indirect indexed addressing mod...
Definition cpu.h:938
#define JUMP_Subroutine(processor, addr)
Procedure that performs a Jump to a subroutine (JSR instruction) located at the address addr.
Definition cpu.h:1275
#define SHIFT_RIGHT_offset(processor, addr, offset)
Procedure that performs a bitshift to the right (LSR operation) at the address (addr + offset) and pl...
Definition cpu.h:1116
#define LD_immediate_Y(processor, d)
Procedure that loads an immediate (const value) in the Y register.
Definition cpu.h:251
#define JUMP_indirect(processor, addr)
Procedure that sets the program counter to a certain indirect address (JMP instruction)
Definition cpu.h:1213
#define COMPARE_absolute_ACC(processor, addr)
Procedure that performs a CMP operation (Z, C, N = A - M) with an absolute addressing mode.
Definition cpu.h:1340
#define INC_X(processor)
Procedure that increments the X register.
Definition cpu.h:406
#define ADD_absolute(processor, addr)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with absolute addressing mode.
Definition cpu.h:692
#define BRANCH_Overflow_S(processor, offset)
Procedure that performs a BVS (branch if positive, if the N flag is clear)
Definition cpu.h:1032
#define BRANCH_Overflow_C(processor, offset)
Procedure that performs a BVC (branch if overflow clear, if the V flag is clear)
Definition cpu.h:1004
#define ROTATION_LEFT_absolute(processor, addr)
Procedure that performs a bit shift with rotation to the left (ROL operation) at the memory address a...
Definition cpu.h:1166
#define GET_D_FLAG(x)
Definition cpu.h:122
#define PUSH_FLAGS(processor)
Procedure that push the processor flags to the top of the stack.
Definition cpu.h:609
#define LD_offset_X(processor, addr, offset)
Procedure that loads a value from memory at address addr+offset to the X register.
Definition cpu.h:278
#define AND_immediate(processor, data)
Procedure that performs a bitwise logic AND (A,Z,N = A & data)
Definition cpu.h:744
#define BRANCH_Carry_C(processor, offset)
Procedure that performs a BCC (if the C flag is clear)
Definition cpu.h:1018
#define STR_absolute_Y(processor, addr)
Procedure that store the Y register value to a memory address.
Definition cpu.h:471
#define ROTATION_LEFT_ACC(processor)
Procedure that performs a bit shift with rotation to the left (ROL operation) on the accumulator....
Definition cpu.h:1149
#define SHIFT_LEFT_offset(processor, addr, offset)
Procedure that performs a bitshift to the left (ASL operation) at the address (addr + offset) and pla...
Definition cpu.h:1107
#define STR_indexed_indirect_ACC(processor, addr, offset)
Procedure that store the accumulator value to a memory address using indexes indirect addressing mode...
Definition cpu.h:526
#define LD_offset_Y(processor, addr, offset)
Procedure that loads a value from memory at address addr+offset to the Y register.
Definition cpu.h:287
#define STACK_END
Definition macros.h:46
#define STACK_START
Definition macros.h:45
#define BIT_7_MASK
Definition macros.h:20
#define BIT_3_MASK
Definition macros.h:24
#define BIT_6_MASK
Definition macros.h:21
#define BIT_0_MASK
Definition macros.h:27
#define BIT_5_MASK
Definition macros.h:22
#define BIT_4_MASK
Definition macros.h:23
#define ERR_ABN_OPCODE
Definition macros.h:17
#define BIT_1_MASK
Definition macros.h:26
#define BIT_2_MASK
Definition macros.h:25
data * memory
Definition mem.h:6
void free_memory(memory mem)
This procedure free the memory pointer.
Definition mem.c:25
void memory_mirroring(memory mem)
This procedure make the memory mirroring.
Definition mem.c:29
@ DEC_Z
DEC Zero Page.
Definition opcodes.h:99
@ INC_AX
INC Absolute, X.
Definition opcodes.h:124
@ LSR_ZX
LSR Zero Page, X.
Definition opcodes.h:166
@ RTI
Return from the current interrupt.
Definition opcodes.h:210
@ TSX
X = sp.
Definition opcodes.h:257
@ CMP_IdX
CMP (Indirect, X)
Definition opcodes.h:85
@ BEQ
If Z = 1.
Definition opcodes.h:41
@ ROL_ZX
ROL Zero Page, X.
Definition opcodes.h:198
@ CMP_IdY
CMP (Indirect), Y.
Definition opcodes.h:86
@ ROL_Z
ROL Zero Page.
Definition opcodes.h:197
@ CMP_AX
CMP Absolute, X.
Definition opcodes.h:83
@ ASL_ZX
ASL Zero Page, X.
Definition opcodes.h:30
@ CMP_A
CMP Absolute.
Definition opcodes.h:82
@ CLI
I = 0.
Definition opcodes.h:73
@ ORA_ZX
ORA Zero Page, X.
Definition opcodes.h:176
@ LDA_AX
LDA Absolute, X.
Definition opcodes.h:144
@ CPY_Z
CPY Zero Page.
Definition opcodes.h:95
@ SBC_ZX
SBC Zero Page, X.
Definition opcodes.h:218
@ BPL
If N = 0.
Definition opcodes.h:55
@ ROL_A
ROL Absolute.
Definition opcodes.h:199
@ STY_Z
STY Zero Page.
Definition opcodes.h:249
@ TYA
ACC = Y.
Definition opcodes.h:263
@ LDX_ZY
LDX Zero Page, Y.
Definition opcodes.h:152
@ SEC
C = 1.
Definition opcodes.h:226
@ ADC_IdX
ADC (Indirect, X)
Definition opcodes.h:12
@ AND_AX
AND Absolute, X.
Definition opcodes.h:21
@ TAX
X = ACC.
Definition opcodes.h:254
@ LDY_ZX
LDY Zero Page, X.
Definition opcodes.h:159
@ ROR_Z
ROR Zero Page.
Definition opcodes.h:204
@ BCS
If C = 1.
Definition opcodes.h:38
@ AND_ZX
AND Zero Page, X.
Definition opcodes.h:19
@ INC_ZX
INC Zero Page, X.
Definition opcodes.h:122
@ LDA_A
LDA Absolute.
Definition opcodes.h:143
@ PLP
flags = pull(); sp = sp + 1;
Definition opcodes.h:193
@ CPX_A
CPX Absolute.
Definition opcodes.h:91
@ ADC_ZX
ADC Zero Page, X.
Definition opcodes.h:8
@ ADC_Z
ADC Zero Page.
Definition opcodes.h:7
@ LDA_I
LDA Immediate.
Definition opcodes.h:140
@ DEC_A
DEC Absolute.
Definition opcodes.h:101
@ CLV
V = 0.
Definition opcodes.h:76
@ BNE
If Z = 0.
Definition opcodes.h:52
@ STY_A
STY Absolute.
Definition opcodes.h:251
@ STX_Z
STX Zero Page.
Definition opcodes.h:244
@ ROL_AX
ROL Absolute, X.
Definition opcodes.h:200
@ ADC_I
ADC Immediate.
Definition opcodes.h:6
@ AND_IdX
AND (Indirect, X)
Definition opcodes.h:23
@ INC_Z
INC Zero Page.
Definition opcodes.h:121
@ BIT_Z
BIT Zero Page.
Definition opcodes.h:45
@ LDY_AX
LDY Absolute, X.
Definition opcodes.h:161
@ DEY
Y = Y - 1.
Definition opcodes.h:108
@ SEI
I = 1.
Definition opcodes.h:232
@ SBC_I
SBC Immediate.
Definition opcodes.h:216
@ AND_I
AND Immediate.
Definition opcodes.h:17
@ CPX_Z
CPX Zero Page.
Definition opcodes.h:90
@ TAY
Definition opcodes.h:269
@ ASL_AX
ASL Absolute, X.
Definition opcodes.h:32
@ INC_A
INC Absolute.
Definition opcodes.h:123
@ CMP_ZX
CMP Zero Page, X.
Definition opcodes.h:81
@ EOR_AY
EOR Absolute, Y.
Definition opcodes.h:116
@ PHP
push(flags); sp = sp - 1;
Definition opcodes.h:187
@ AND_AY
AND Absolute, Y.
Definition opcodes.h:22
@ EOR_ZX
EOR Zero Page, X.
Definition opcodes.h:113
@ BRK
Break instruction.
Definition opcodes.h:58
@ ADC_AX
ADC Absolute, X.
Definition opcodes.h:10
@ LDA_ZX
LDA Zero Page, X.
Definition opcodes.h:142
@ ROR_Ac
ROR Accumulator.
Definition opcodes.h:203
@ AND_IdY
AND (Indirect), Y.
Definition opcodes.h:24
@ BIT_A
BIT Absolute.
Definition opcodes.h:46
@ EOR_AX
EOR Absolute, X.
Definition opcodes.h:115
@ SBC_IdY
SBC (Indirect), Y.
Definition opcodes.h:223
@ ORA_AY
ORA Absolute, Y.
Definition opcodes.h:179
@ SBC_AX
SBC Absolute, X.
Definition opcodes.h:220
@ CLC
C = 0.
Definition opcodes.h:67
@ STA_Z
STA Zero Page.
Definition opcodes.h:235
@ LDA_Z
LDA Zero Page.
Definition opcodes.h:141
@ STA_A
STA Absolute.
Definition opcodes.h:237
@ TXA
ACC = X.
Definition opcodes.h:260
@ STA_AY
STA Absolute, Y.
Definition opcodes.h:239
@ ADC_IdY
ADC (Indirect), Y.
Definition opcodes.h:13
@ LDX_Z
LDX Zero Page.
Definition opcodes.h:151
@ CPX_I
CPX Immediate.
Definition opcodes.h:89
@ ROR_ZX
ROR Zero Page, X.
Definition opcodes.h:205
@ ORA_A
ORA Absolute.
Definition opcodes.h:177
@ AND_Z
AND Zero Page.
Definition opcodes.h:18
@ STA_IdY
STA (Indirect), Y.
Definition opcodes.h:241
@ CMP_Z
CMP Zero Page.
Definition opcodes.h:80
@ CPY_I
CPY Immediate.
Definition opcodes.h:94
@ ASL_Z
ASL Zero Page.
Definition opcodes.h:29
@ BCC
If C = 0.
Definition opcodes.h:35
@ CPY_A
CPY Absolute.
Definition opcodes.h:96
@ EOR_I
EOR Immediate.
Definition opcodes.h:111
@ TXS
Definition opcodes.h:266
@ SBC_IdX
SBC (Indirect, X)
Definition opcodes.h:222
@ LDX_AY
LDX Absolute, Y.
Definition opcodes.h:154
@ CMP_I
CMP Immediate.
Definition opcodes.h:79
@ STY_ZX
STY Zero Page, X.
Definition opcodes.h:250
@ STA_AX
STA Absolute, X.
Definition opcodes.h:238
@ LDX_I
LDX Immediate.
Definition opcodes.h:150
@ CLD
D = 0.
Definition opcodes.h:70
@ ROL_Ac
ROL Accumulator.
Definition opcodes.h:196
@ LDA_AY
LDA Absolute, Y.
Definition opcodes.h:145
@ ORA_IdY
ORA (Indirect), Y.
Definition opcodes.h:181
@ STA_IdX
STA (Indirect, X)
Definition opcodes.h:240
@ LSR_AX
LSR Absolute, X.
Definition opcodes.h:168
@ ROR_AX
ROR Absolute, X.
Definition opcodes.h:207
@ STX_ZY
STX Zero Page, Y.
Definition opcodes.h:245
@ PLA
ACC = pull(); sp = sp + 1;.
Definition opcodes.h:190
@ LDY_A
LDY Absolute.
Definition opcodes.h:160
@ BVC
If V = 0.
Definition opcodes.h:61
@ STA_ZX
STA Zero Page, X.
Definition opcodes.h:236
@ ASL_Ac
ASL Accumulator.
Definition opcodes.h:28
@ EOR_IdX
EOR (Indirect, X)
Definition opcodes.h:117
@ LDY_Z
LDY Zero Page.
Definition opcodes.h:158
@ LSR_A
LSR Absolute.
Definition opcodes.h:167
@ INY
Y = Y + 1.
Definition opcodes.h:130
@ DEC_ZX
DEC Zero Page, X.
Definition opcodes.h:100
@ LSR_Z
LSR Zero Page.
Definition opcodes.h:165
@ EOR_IdY
EOR (Indirect), Y.
Definition opcodes.h:118
@ AND_A
AND Absolute.
Definition opcodes.h:20
@ LDA_IdX
LDA (Indirect, X)
Definition opcodes.h:146
@ LDX_A
LDX Absolute.
Definition opcodes.h:153
@ ADC_AY
ADC Absolute, Y.
Definition opcodes.h:11
@ BMI
iF N = 1
Definition opcodes.h:49
@ LDA_IdY
LDA (Indirect), Y.
Definition opcodes.h:147
@ LSR_Ac
LSR Accumulator.
Definition opcodes.h:164
@ SBC_A
SBC Absolute.
Definition opcodes.h:219
@ DEC_AX
DEC Absolute, X.
Definition opcodes.h:102
@ PHA
push(ACC); sp = sp - 1;
Definition opcodes.h:184
@ ORA_Z
ORA Zero Page.
Definition opcodes.h:175
@ BVS
If V = 1.
Definition opcodes.h:64
@ ORA_IdX
ORA (Indirect, X)
Definition opcodes.h:180
@ INX
X = X + 1.
Definition opcodes.h:127
@ CMP_AY
CMP Absolute, Y.
Definition opcodes.h:84
@ ROR_A
ROR Absolute.
Definition opcodes.h:206
@ ADC_A
ADC Absolute.
Definition opcodes.h:9
@ SBC_Z
SBC Zero Page.
Definition opcodes.h:217
@ RTS
Return from the current subroutine.
Definition opcodes.h:213
@ JMP_A
JMP Absolute.
Definition opcodes.h:133
@ LDY_I
LDY Immediate.
Definition opcodes.h:157
@ ASL_A
ASL Absolute.
Definition opcodes.h:31
@ SED
D = 1.
Definition opcodes.h:229
@ ORA_I
ORA Immediate.
Definition opcodes.h:174
@ ORA_AX
ORA Absolute, X.
Definition opcodes.h:178
@ SBC_AY
SBC Absolute, Y.
Definition opcodes.h:221
@ STX_A
STX Absolute.
Definition opcodes.h:246
@ EOR_Z
EOR Zero Page.
Definition opcodes.h:112
@ JMP_Id
JMP Indirect.
Definition opcodes.h:134
@ NOP
No Operation.
Definition opcodes.h:171
@ DEX
X = X - 1.
Definition opcodes.h:105
@ EOR_A
EOR Abolute.
Definition opcodes.h:114
@ JSR
Jump to the subroutine.
Definition opcodes.h:137
This structure will be used to represent the state of the Central Processing Unit (CPU) of our emulat...
Definition cpu.h:27
data cache
A 8 bit reserved space that I use for some operations.
Definition cpu.h:30
data accumulator
A 8 bit register used to perform operations.
Definition cpu.h:31
data register_y
A 8 bit register. Commonly used to hold offset and counters.
Definition cpu.h:33
data flags
NVPBDIZC.
Definition cpu.h:35
address program_counter
An address pointing to the next instruction to be executed.
Definition cpu.h:28
unsigned char cycle_counter
The cycle counter. The counter is decremented every step.
Definition cpu.h:37
data stack_pointer
A register that holds the 8 lower bytes of the address 0x11??.
Definition cpu.h:29
memory mem
A direct access to the Emulator Memory.
Definition cpu.h:39
data register_x
A 8 bit register. Commonly used to hold offset and counters.
Definition cpu.h:32
two_bytes_word address
Definition of the address format used by the CPU.
Definition types.h:12
byte errcode_t
Definition of the error code type used by some function.
Definition types.h:15
byte data
Definition of the data format used by the CPU.
Definition types.h:11