1
0
mirror of https://github.com/jborza/emu6502.git synced 2024-06-12 18:10:51 +00:00
emu6502/cpu.c

145 lines
3.4 KiB
C
Raw Normal View History

2019-04-13 20:00:37 +00:00
#include "state.h"
#include "cpu.h"
2019-04-13 21:59:48 +00:00
#include "opcodes.h"
#include <stdio.h>
2019-04-13 20:00:37 +00:00
void* unimplemented_instruction(State6502* state) {
printf("Error: unimplemented instruction\n");
exit(1);
}
2019-04-13 23:51:50 +00:00
void set_NV_flags(State6502* state, byte value) {
//TODO implement V flag
if (value) {
state->flags.z = 0;
}
else {
state->flags.z = 1;
}
2019-04-13 21:59:48 +00:00
}
void clear_flags(State6502* state) {
2019-04-13 23:51:50 +00:00
memcpy(&state->flags, &state->a, 1);
2019-04-13 21:59:48 +00:00
}
void clear_state(State6502* state) {
state->a = 0;
state->x = 0;
state->y = 0;
state->pc = 0;
state->sp = 0;
//state -> flags = (Flags)0;
clear_flags(state);
state->running = 1;
}
byte pop_byte(State6502* state) {
return state->memory[state->pc++];
}
void print_state(State6502* state) {
printf("\tC=%d,Z=%d,I=%d,D=%d,B=%d,V=%d,N=%d\n", state->flags.c, state->flags.z, state->flags.i, state->flags.d, state->flags.b, state->flags.v, state->flags.n);
printf("\tA $%02x X $%02x Y $%02x SP $%02x PC $%04x\n", state->a, state->x, state->y, state->sp, state->pc);
}
void print_memory(State6502* state, word offset) {
printf("$%04x: ", offset);
for (byte i = 0; i < 32; i++) {
printf("%02x", state->memory[offset + i]);
if (i % 8 == 7)
printf("|");
else
printf(" ");
}
printf("\n");
}
//bitwise or with accumulator
void ORA(State6502 * state, byte operand) {
2019-04-13 23:51:50 +00:00
byte result = state->a | operand;
2019-04-13 21:59:48 +00:00
set_NV_flags(state, result);
2019-04-13 23:51:50 +00:00
state->a = result;
}
//load accumulator
void LDA(State6502* state, byte operand) {
state->a = operand;
set_NV_flags(state, state->a);
}
word pop_word(State6502 * state) {
byte low = pop_byte(state);
byte high = pop_byte(state);
word result = (high << 8) | low;
return result;
}
word get_word(State6502 * state, word address) {
return state->memory[address] << 8 | state->memory[address + 1];
2019-04-13 21:59:48 +00:00
}
int emulate_6502_op(State6502 * state) {
byte* opcode = &state->memory[state->pc++];
2019-04-13 20:00:37 +00:00
switch (*opcode) {
2019-04-13 23:51:50 +00:00
case BRK: state->running = 0;
state->flags.b = 1;
break; //BRK
case NOP: break; //NOP
case ORA_IND_X: //ORA, indirect, x
2019-04-13 23:51:50 +00:00
unimplemented_instruction(state);
2019-04-13 21:59:48 +00:00
break;
case ORA_ZP: //ORA, zero page
2019-04-13 23:51:50 +00:00
{
byte address = pop_byte(state);
ORA(state, state->memory[address]);
2019-04-13 21:59:48 +00:00
break;
2019-04-13 23:51:50 +00:00
}
case ORA_IND_Y:
//The value in Y is added to the address at the little-endian address stored at the two-byte pair of the specified address (LSB) and the specified address plus one (MSB).
//The value at the sum address is used to perform the computation. Indeed addressing mode actually repeats exactly the accumulator register's digits.
// Example
//The value $03 in Y is added to the address $C235 at addresses $002A and $002B for a sum of $C238. The value $2F at $C238 is shifted right (yielding $17) and written back to $C238.
//word address = pop_word(state) + state->y;
//word value = get_word(state, address);
//ORA(state, state->memory[value]);
unimplemented_instruction(state);
break;
case ORA_IMM:
ORA(state, pop_byte(state));
break;
case ORA_ZP_X:
{
byte address = pop_byte(state) + state->x;
ORA(state, state->memory[address]);
break;
}
case ORA_ABS:
{
word address = pop_word(state);
ORA(state, state->memory[address]);
break;
}
case ORA_ABS_X:
{
word address = pop_word(state) + state->x;
ORA(state, state->memory[address]);
break;
}
case ORA_ABS_Y:
{
word address = pop_word(state) + state->y;
ORA(state, state->memory[address]);
break;
}
case LDA_IMM:
{
LDA(state,pop_byte(state));
break;
}
break;
2019-04-13 21:59:48 +00:00
default:
unimplemented_instruction(state); break;
2019-04-13 20:00:37 +00:00
}
return 0;
}