Skip to content

Commit

Permalink
refactor complete, now passed nestest (upto illegal opcodes)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwillsey committed Feb 10, 2014
1 parent a5d86e3 commit 08b7a62
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 33 deletions.
70 changes: 44 additions & 26 deletions 6502.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,10 @@ void set_zn_flags (cpu *c, byte b) {
* handle incrementing the PC according to the number of arguments */

/* accumulator
* this addressing mode is an expection in that the operation works on a
* register as opposed to on memory. Operations that this applies to need
* to be aware of this, so we'll simply send -1.
* a few operations can work on the accumulator or memory, those have bee
* split into 2 separate functions, where the accumulator take 1 less arg.
*/

static const addr am_acc = -1;

/* immediate
* the constant immediately follows in instruction in memory
* we will work with the invariant that the PC is incremented until
Expand All @@ -102,23 +99,23 @@ addr am_imm (cpu *c) {
* bytes of memory can be addressed (0x0000 - 0x00FF)
*/
addr am_zer (cpu *c) {
return (addr)mem_read(c->mem, c->PC++);
return mem_read(c->mem, c->PC++);
}

/* zero page,x
* address to be accessed is the 8-bit value given in the instruction
* summed with the X register
*/
addr am_zex (cpu *c) {
return (addr)(mem_read(c->mem, c->PC++) + c->X);
return (byte)(mem_read(c->mem, c->PC++) + c->X);
}

/* zero page,y
* address to be accessed is the 8-bit value given in the instruction
* summed with the X register
*/
addr am_zey (cpu *c) {
return (addr)(mem_read(c->mem, c->PC++) + c->Y);
return (byte)(mem_read(c->mem, c->PC++) + c->Y);
}

/* relative
Expand Down Expand Up @@ -473,7 +470,7 @@ void INY (cpu *c) {

/* decrement a memory location */
void DEC (cpu *c, addr a) {
byte b = mem_read(c->mem, a) + 1;
byte b = mem_read(c->mem, a) - 1;
mem_write(c->mem, a, b);
set_zn_flags(c, b);
}
Expand All @@ -494,52 +491,75 @@ void DEY (cpu *c) {
* ----- shifts -----
*/

/* these operations can work directly on the accumulator, which will
* be indicated by an address of -1 */
/* these operations can work directly on the accumulator,
* and they will be split off into separate functions */

/* arithmetic shift left */
void ASLa (cpu *c) {
set_flag(c, C, c->A & 0x80);
c->A <<= 1;
set_zn_flags(c, c->A);
}

void ASL (cpu *c, addr a) {
byte b = mem_read(c->mem, a);
/* set carry if we're shifting a bit out */
set_flag(c, C, b & 0x80);
b <<= 1;
mem_write(c->mem, a, b);
set_zn_flags(c, b);
}

/* logical shift right */
void LSRa (cpu *c) {
set_flag(c, C, c->A & 0x1);
c->A >>= 1;
set_zn_flags(c, c->A);
}

void LSR (cpu *c, addr a) {
byte b = mem_read(c->mem, a);
/* set carry if we're shifting a bit out */
set_flag(c, C, b & 0x1);
b >>= 1;
mem_write(c->mem, a, b);
set_zn_flags(c, b);
}

/* rotate left */
void ROLa (cpu *c) {
byte bit;
bit = (c->A >> 7 & 0x1);
c->A = (c->A << 1) | get_flag(c, C);
set_flag(c, C, bit);
set_zn_flags(c, c->A);
}

void ROL (cpu *c, addr a) {
byte bit, b;
b = mem_read(c->mem, a);
/* save most significant bit to put in carry */
bit = (b >> 7) & 0x1;
b = (b << 1) | get_flag(c, C);
mem_write(c->mem, a, b);
set_flag(c, C, bit);
/* set zero and negative flags */
set_zn_flags(c, b);
}


/* rotate right */
void ROR (cpu *c, addr a) {
void RORa (cpu *c) {
byte bit;
bit = c->A & 0x1;
c->A = (c->A >> 1) | (get_flag(c, C) << 7);
set_flag(c, C, bit);
set_zn_flags(c, c->A);
}

void ROR (cpu *c, addr a) {
byte bit, b;
b = mem_read(c->mem, a);
/* save most significant bit to put in carry */
bit = b & 0x1;
b = (b >> 1) | (get_flag(c, C) << 7);
mem_write(c->mem, a, b);
set_flag(c, C, bit);
/* set zero and negative flags */
set_zn_flags(c, b);
}

Expand All @@ -551,15 +571,13 @@ void ROR (cpu *c, addr a) {

/* jump to another location */
void JMP (cpu *c, addr a) {
byte b = mem_read(c->mem, a);
printf("jumping to %04x\n", b);
c->PC = b;
c->PC = a;
}

/* jump to subroutine */
void JSR (cpu *c, addr a) {
push_word(c, c->PC - 1);
c->PC = mem_read(c->mem, a);
c->PC = a;
}

/* return from subroutine */
Expand Down Expand Up @@ -759,7 +777,7 @@ int cpu_step (cpu *c) {
case 0x21: AND(c, am_inx(c)); break;
case 0x31: AND(c, am_iny(c)); break;
/* ASL */
case 0x0a: ASL(c, am_acc); break;
case 0x0a: ASLa(c); break;
case 0x06: ASL(c, am_zer(c)); break;
case 0x16: ASL(c, am_zex(c)); break;
case 0x0e: ASL(c, am_abs(c)); break;
Expand Down Expand Up @@ -849,7 +867,7 @@ int cpu_step (cpu *c) {
case 0xac: LDY(c, am_abs(c)); break;
case 0xbc: LDY(c, am_abx(c)); break;
/* LSR */
case 0x4a: LSR(c, am_acc); break;
case 0x4a: LSRa(c); break;
case 0x46: LSR(c, am_zer(c)); break;
case 0x56: LSR(c, am_zex(c)); break;
case 0x4e: LSR(c, am_abs(c)); break;
Expand Down Expand Up @@ -881,13 +899,13 @@ int cpu_step (cpu *c) {
case 0x88: DEY(c); /* implied operand */ break;
case 0xc8: INY(c); /* implied operand */ break;
/* ROL */
case 0x2a: ROL(c, am_acc); break;
case 0x2a: ROLa(c); break;
case 0x26: ROL(c, am_zer(c)); break;
case 0x36: ROL(c, am_zex(c)); break;
case 0x2e: ROL(c, am_abs(c)); break;
case 0x3e: ROL(c, am_abx(c)); break;
/* ROR */
case 0x6a: ROR(c, am_acc); break;
case 0x6a: RORa(c); break;
case 0x66: ROR(c, am_zer(c)); break;
case 0x76: ROR(c, am_zex(c)); break;
case 0x6e: ROR(c, am_abs(c)); break;
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CC = gcc
CFLAGS = -Wall
CFLAGS = -Wall -g

all: nes

Expand Down
32 changes: 28 additions & 4 deletions memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,45 @@
#include "memory.h"

void mem_init (memory *mem, int size) {
mem->arr = malloc(sizeof(byte)*size);
int a; //need a to be int so it will go over 0xffff
mem->ram = malloc(sizeof(byte) * size);
mem->mirrors = malloc(sizeof(addr) * size);
mem->write_cbs = malloc(sizeof(void*) * size);
mem->read_cbs = malloc(sizeof(void*) * size);

for (a = 0; a < size; a++)
mem->mirrors[a] = a;
}

void mem_write (memory *mem, addr a, byte b) {
mem->arr[a] = b;
addr a1 = mem->mirrors[a];
if (mem->write_cbs[a1])
(mem->write_cbs[a1])(a1,b);
else
mem->ram[a1] = b;
}

byte mem_read (memory *mem, addr a) {
return mem->arr[a];
addr a1 = mem->mirrors[a];
if (mem->read_cbs[a1])
return (mem->read_cbs[a1])(a1);
else
return mem->ram[a1];
}

void mem_destroy (memory *mem) {
free(mem->arr);
free(mem->ram);
free(mem->read_cbs);
free(mem->write_cbs);
}

void mem_mirror (memory *mem, addr start, addr end, int size) {
addr a;
for (a = start; a <= end; a++) {
mem->mirrors[a] = a % size;
}
}




Expand Down
7 changes: 6 additions & 1 deletion memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@ typedef uint8_t byte;
typedef uint16_t addr;

typedef struct {
byte *arr;
byte *ram;
addr *mirrors;
byte (**read_cbs)(addr);
void (**write_cbs)(addr, byte);
} memory;

void mem_init (memory *mem, int size);
void mem_write (memory *mem, addr a, byte b);
byte mem_read (memory *mem, addr a);
void mem_destroy (memory *mem);

/* a convenience function used to set up memory mirroring */
void mem_mirror (memory *mem, addr start, addr end, int size);



Expand Down
3 changes: 2 additions & 1 deletion nes.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ int main (int argc, char** argv) {
/* fread(nes_cpu.cartidge_lower_bank, sizeof(byte), in_stat.st_size, in); */

/* for the nestest rom */
fread(mem.arr+0xc000-16, sizeof(byte), 0x4000, in);
fread(mem.ram+0xc000-16, sizeof(byte), 0x4000, in);
nes_cpu.PC = 0xc000;


int i;
for(i = 0; i < 10000; i++) {
cpu_step(&nes_cpu);
Expand Down

0 comments on commit 08b7a62

Please sign in to comment.