mirror of
https://github.com/raxracks/6502.git
synced 2024-12-02 00:11:10 +13:00
first commit
This commit is contained in:
commit
b26428cdee
12 changed files with 378 additions and 0 deletions
7
Makefile
Normal file
7
Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
emulator: emulator.c
|
||||
gcc emulator.c -o emulator -g -Iinclude
|
||||
hello: hello.asm
|
||||
ca65 hello.asm -o hello.o
|
||||
ld65 hello.o -o hello -C config.cfg
|
||||
run: hello emulator
|
||||
./emulator hello
|
9
config.cfg
Normal file
9
config.cfg
Normal file
|
@ -0,0 +1,9 @@
|
|||
MEMORY {
|
||||
RAM: start = $0000, size = $4000, type = rw;
|
||||
ROM: start = $8000, size = $8000, type = ro;
|
||||
}
|
||||
|
||||
SEGMENTS {
|
||||
CODE: load = "ROM", type = ro;
|
||||
DATA: load = "ROM", type = ro;
|
||||
}
|
BIN
emulator
Executable file
BIN
emulator
Executable file
Binary file not shown.
272
emulator.c
Normal file
272
emulator.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
#include <stdio.h>
|
||||
#include <slibs/slibs.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define NEGATIVE 1 << 7
|
||||
#define OVERFLOW 1 << 6
|
||||
#define BREAK 1 << 4
|
||||
#define DECIMAL 1 << 3
|
||||
#define INTERRUPT 1 << 2
|
||||
#define ZERO 1 << 1
|
||||
#define CARRY 1 << 0
|
||||
|
||||
typedef struct {
|
||||
uint8_t A;
|
||||
uint8_t X;
|
||||
uint8_t Y;
|
||||
uint8_t SP;
|
||||
uint8_t P;
|
||||
uint16_t PC;
|
||||
} CPU;
|
||||
|
||||
CPU cpu = { 0 };
|
||||
uint8_t* memory;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
assert(argc > 1);
|
||||
|
||||
sl_string code = { 0 };
|
||||
sl_read_file(argv[1], &code);
|
||||
|
||||
memory = malloc(sizeof(uint8_t) * 0xffff);
|
||||
memcpy(memory + 0x8000, code.data, code.size);
|
||||
|
||||
for(cpu.PC = 0; cpu.PC < code.size; cpu.PC++) {
|
||||
uint8_t opcode = code.data[cpu.PC];
|
||||
uint8_t one = code.data[cpu.PC + 1];
|
||||
uint8_t two = code.data[cpu.PC + 2];
|
||||
uint16_t word = (two << 8) | one;
|
||||
|
||||
uint8_t h_nib = (opcode >> 4) & 0xF;
|
||||
uint8_t l_nib = opcode & 0xF;
|
||||
|
||||
printf("%d: 0x%02X (h_nib: 0x%X, l_nib: 0x%X)\n", cpu.PC, opcode, h_nib, l_nib);
|
||||
|
||||
switch(h_nib) {
|
||||
case 0x8:
|
||||
switch(l_nib) {
|
||||
case 0x1:
|
||||
printf(" ∟ STA ($%02X, X)\n", one);
|
||||
memory[memory[one + cpu.X]] = cpu.A;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x5:
|
||||
printf(" ∟ STA $%02X\n", one);
|
||||
memory[one] = cpu.A;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x6:
|
||||
printf(" ∟ STX $%02X\n", one);
|
||||
memory[one] = cpu.X;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0xD:
|
||||
printf(" ∟ STA $%04X\n", word);
|
||||
memory[word] = cpu.A;
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
case 0xE:
|
||||
printf(" ∟ STX $%04X\n", word);
|
||||
memory[word] = cpu.X;
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x9:
|
||||
switch(l_nib) {
|
||||
case 0x1:
|
||||
printf(" ∟ STA ($%02X), Y\n", one);
|
||||
memory[memory[one] + cpu.Y] = cpu.A;
|
||||
cpu.PC++;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
printf(" ∟ STA $%02X, X\n", word);
|
||||
memory[one + cpu.X] = cpu.A;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x9:
|
||||
printf(" ∟ STA $%04X, Y\n", word);
|
||||
memory[word + cpu.Y] = cpu.A;
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
case 0xD:
|
||||
printf(" ∟ STA $%04X, X\n", word);
|
||||
memory[word + cpu.X] = cpu.A;
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xA:
|
||||
switch(l_nib) {
|
||||
case 0x0:
|
||||
printf(" ∟ LDY #$%02X\n", one);
|
||||
cpu.Y = one;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x1:
|
||||
printf(" ∟ LDA ($%02X, X)\n", one);
|
||||
cpu.A = memory[memory[one + cpu.X]];
|
||||
printf("addr: %x val: %x\n", memory[one + cpu.X], cpu.A);
|
||||
cpu.PC++;
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
printf(" ∟ LDX #$%02X\n", one);
|
||||
cpu.X = one;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x4:
|
||||
printf(" ∟ LDY $%02X\n", one);
|
||||
cpu.Y = memory[one];
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x5:
|
||||
printf(" ∟ LDA $%02X\n", one);
|
||||
cpu.A = memory[one];
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x6:
|
||||
printf(" ∟ LDX $%02X\n", one);
|
||||
cpu.X = memory[one];
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x9:
|
||||
printf(" ∟ LDA #$%02X\n", one);
|
||||
cpu.A = one;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0xC:
|
||||
printf(" ∟ LDY $%04X\n", word);
|
||||
cpu.Y = memory[word];
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
case 0xD:
|
||||
printf(" ∟ LDA $%04X\n", word);
|
||||
cpu.A = memory[word];
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
case 0xE:
|
||||
printf(" ∟ LDX $%04X\n", word);
|
||||
cpu.X = memory[word];
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xB:
|
||||
switch(l_nib) {
|
||||
case 0x1:
|
||||
printf(" ∟ LDA ($%02X), Y\n", one);
|
||||
cpu.A = memory[memory[one] + cpu.Y];
|
||||
printf("addr: %x val: %x\n", memory[one] + cpu.Y, cpu.A);
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x4:
|
||||
printf(" ∟ LDY $%02X, X\n", one);
|
||||
cpu.Y = memory[one + cpu.X];
|
||||
printf("addr: %x val: %x\n", one + cpu.X, cpu.Y);
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x5:
|
||||
printf(" ∟ LDA $%02X, X\n", one);
|
||||
cpu.A = memory[one + cpu.X];
|
||||
printf("addr: %x val: %x\n", one + cpu.X, cpu.A);
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x6:
|
||||
printf(" ∟ LDX $%02X, Y\n", one);
|
||||
cpu.X = memory[one + cpu.Y];
|
||||
printf("addr: %x val: %x\n", one + cpu.Y, cpu.X);
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x9:
|
||||
printf(" ∟ LDA $%04X, Y\n", word);
|
||||
cpu.A = memory[word + cpu.Y];
|
||||
printf("addr: %x val: %x\n", word + cpu.Y, cpu.A);
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0xC:
|
||||
printf(" ∟ LDY $%04X, X\n", word);
|
||||
cpu.Y = memory[word + cpu.X];
|
||||
printf("addr: %x val: %x\n", word + cpu.X, cpu.Y);
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
case 0xD:
|
||||
printf(" ∟ LDA $%04X, X\n", word);
|
||||
cpu.A = memory[word + cpu.X];
|
||||
printf("addr: %x val: %x\n", word + cpu.X, cpu.A);
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
case 0xE:
|
||||
printf(" ∟ LDX $%04X, Y\n", word);
|
||||
cpu.X = memory[word + cpu.Y];
|
||||
printf("addr: %x val: %x\n", word + cpu.Y, cpu.X);
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xC:
|
||||
switch(l_nib) {
|
||||
case 0x8:
|
||||
printf(" ∟ INY\n");
|
||||
cpu.Y++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xE:
|
||||
switch(l_nib) {
|
||||
case 0x6:
|
||||
printf(" ∟ INC $%02X\n", one);
|
||||
memory[one]++;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0x8:
|
||||
printf(" ∟ INX\n");
|
||||
cpu.X++;
|
||||
break;
|
||||
case 0xE:
|
||||
printf(" ∟ INC $%04X\n", word);
|
||||
memory[word]++;
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xF:
|
||||
switch(l_nib) {
|
||||
case 0x6:
|
||||
printf(" ∟ INC $%02X, X\n", one);
|
||||
memory[one + cpu.X]++;
|
||||
cpu.PC++;
|
||||
break;
|
||||
case 0xE:
|
||||
printf(" ∟ INC $%04X, X\n", word);
|
||||
memory[word + cpu.X]++;
|
||||
cpu.PC += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf(" ∟ Unimplemented\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("CPU State:\n"
|
||||
"A\t:\t0x%08X\n"
|
||||
"X\t:\t0x%08X\n"
|
||||
"Y\t:\t0x%08X\n"
|
||||
"SP\t:\t0x%08X\n"
|
||||
"P\t:\t0x%08X\n"
|
||||
"PC\t:\t0x%016X\n\n"
|
||||
, cpu.A, cpu.X, cpu.Y, cpu.SP, cpu.P, cpu.PC);
|
||||
|
||||
printf("Memory State:\n");
|
||||
for(int i = 0; i < 0xffff; i++) {
|
||||
if(memory[i] != 0x0) {
|
||||
printf("0x%04X: 0x%02X (0b%08b)\n", i, memory[i], memory[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
40
game.asm
Normal file
40
game.asm
Normal file
|
@ -0,0 +1,40 @@
|
|||
.segment "CODE"
|
||||
|
||||
.proc main
|
||||
main:
|
||||
; Initialize PPU
|
||||
LDA #%10000000 ; Set the bit 7 to $2000 to use $2000-$2FFF for nametables
|
||||
STA $2000
|
||||
LDA #%00011110 ; Enable rendering, enable sprites, and make sure background is visible
|
||||
STA $2001
|
||||
|
||||
; Load sprite data into OAM
|
||||
LDX #0 ; Initialize X register to zero
|
||||
LDA SpriteData,X ; Load the first byte of sprite data
|
||||
STA $0200,X ; Store it in the Object Attribute Memory (OAM)
|
||||
INX ; Increment X to load the next byte
|
||||
LDA SpriteData,X ; Load the second byte of sprite data (attributes)
|
||||
STA $0200,X ; Store it in OAM
|
||||
INX ; Increment X to load the next byte (X position)
|
||||
LDA SpriteData,X ; Load the third byte of sprite data (X position)
|
||||
STA $0200,X ; Store it in OAM
|
||||
|
||||
; Infinite loop
|
||||
forever:
|
||||
JMP forever
|
||||
|
||||
.endproc
|
||||
|
||||
.segment "DATA"
|
||||
|
||||
SpriteData:
|
||||
.byte $00 ; Tile index for the sprite
|
||||
.byte $20 ; Attributes (palette, flipping, etc.)
|
||||
.byte $80 ; X position of the sprite
|
||||
; Additional sprite data can be added here
|
||||
|
||||
.segment "BSS"
|
||||
|
||||
; Define uninitialized memory (if needed)
|
||||
|
||||
|
BIN
hello
Normal file
BIN
hello
Normal file
Binary file not shown.
4
hello.asm
Normal file
4
hello.asm
Normal file
|
@ -0,0 +1,4 @@
|
|||
LDA #10
|
||||
LDX #$1
|
||||
STA $20
|
||||
INC $2000, X
|
BIN
hello.o
Normal file
BIN
hello.o
Normal file
Binary file not shown.
BIN
helloworld.nes
Normal file
BIN
helloworld.nes
Normal file
Binary file not shown.
39
implemented.txt
Normal file
39
implemented.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
==== LDA (completed) ====
|
||||
LDA #
|
||||
LDA $ (Z)
|
||||
LDA $ (A)
|
||||
LDA $, X (Z)
|
||||
LDA $, X (A)
|
||||
LDA $, Y (A)
|
||||
LDA ($, X)
|
||||
LDA ($), Y
|
||||
|
||||
==== LDX (completed) ====
|
||||
LDX #
|
||||
LDX $ (Z)
|
||||
LDX $ (A)
|
||||
LDX $, Y (Z)
|
||||
LDX $, Y (A)
|
||||
|
||||
==== LDY (completed) ====
|
||||
LDY #
|
||||
LDY $ (Z)
|
||||
LDY $ (A)
|
||||
LDY $, X (Z)
|
||||
LDY $, X (A)
|
||||
|
||||
==== STA (completed) ====
|
||||
STA $ (Z)
|
||||
STA $ (A)
|
||||
STA $, X (Z)
|
||||
STA $, X (A)
|
||||
STA ($, X)
|
||||
STA ($), Y
|
||||
|
||||
==== INC (completed) ====
|
||||
INX
|
||||
INY
|
||||
INC $ (Z)
|
||||
INC $ (A)
|
||||
INC $, X (Z)
|
||||
INC $, X (A)
|
1
include/slibs
Submodule
1
include/slibs
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 63edb9343b6787883a667b69ece86bde005ab311
|
6
temp.asm
Normal file
6
temp.asm
Normal file
|
@ -0,0 +1,6 @@
|
|||
LDA hello, X
|
||||
INX
|
||||
LDA hello, X
|
||||
|
||||
.DATA
|
||||
hello: .byte "hello world", 0
|
Loading…
Add table
Reference in a new issue