static int current_exec_index;
static int exec_done;
static int intr_done;
+static int bus_status;
unsigned char load_memory(unsigned short addr);
unsigned short load_addr(unsigned short addr, int cycle);
void store_memory(unsigned short addr, unsigned char data);
+int bus_ready(void);
+#define BUS_READY_CHECK() \
+ if ((bus_status = bus_ready()) != TRUE) { return FALSE; }
unsigned char get_cpu_data_buf(void);
void set_cpu_data_buf(unsigned char data);
*
* */
static int load_addr_mode(int *done) {
+ BUS_READY_CHECK()
+
switch (current_inst->addr_mode) {
case ADDR_MODE_ACC:
case ADDR_MODE_IMP:
* store into memory in various addressing mode.
* */
static int store_addr_mode(unsigned char data, int *done) {
+ BUS_READY_CHECK()
+
switch (current_inst->addr_mode) {
case ADDR_MODE_ACC:
case ADDR_MODE_IMP:
* for inc/dec/shift operation
* */
static int memory_to_memory(int *do_operation, int *done) {
+ BUS_READY_CHECK()
+
switch (current_inst->addr_mode) {
case ADDR_MODE_ACC:
case ADDR_MODE_IMP:
/*------------- stack operation.. ---------------------*/
//stack operation takes two cycles.
-static void push(unsigned char data) {
+static int push(unsigned char data) {
+ BUS_READY_CHECK()
+
store_memory(STACK_BASE + cpu_reg.sp, data);
cpu_reg.sp--;
+ return TRUE;
}
-static unsigned char pop(void) {
+static int pop(void) {
+ BUS_READY_CHECK()
+
cpu_reg.sp++;
- return load_memory(STACK_BASE + cpu_reg.sp);
+ load_memory(STACK_BASE + cpu_reg.sp);
+ return TRUE;
}
/*---------- instruction implementations. -----------------*/
}
static int jmp(int cycle, int *done) {
+ BUS_READY_CHECK()
+
switch (current_inst->addr_mode) {
case ADDR_MODE_ABS:
//takes 2 cycles.
if (current_exec_index == 0) {
//save return addr(-1) hi.
//pc + 1 => jsr abslo abshi - 1
- push((cpu_reg.pc + 1) >> 8);
- return TRUE;
+ return push((cpu_reg.pc + 1) >> 8);
}
//cycle 2
else if (current_exec_index == 1) {
//save return addr(-1) low.
- push(cpu_reg.pc + 1);
- return TRUE;
+ return push(cpu_reg.pc + 1);
}
//cycle 3,4
else if (current_exec_index < 4) {
static int push_op(unsigned char data, int *done) {
//cycle 1
if (current_exec_index == 0) {
- push(data);
- return TRUE;
+ return push(data);
}
//cycle 2
else if (current_exec_index == 1) {
static int pull_op(int *done) {
//cycle 1
if (current_exec_index == 0) {
- pop();
- return TRUE;
+ return pop();
}
//cycle 2
else if (current_exec_index == 1) {
//cycle 1
if (current_exec_index == 0) {
//pop statu reg.
- pop();
- return TRUE;
+ return pop();
}
//cycle 2
else if (current_exec_index == 1) {
data = get_cpu_data_buf();
memcpy(&cpu_reg.status, &data, sizeof(data));
//pop return addr low.
- pop();
- return TRUE;
+ return pop();
}
//cycle 3
else if (current_exec_index == 2) {
//set return addr low.
set_cpu_addr_buf(get_cpu_data_buf());
//pop return addr hi.
- pop();
- return TRUE;
+ return pop();
}
//cycle 4
else if (current_exec_index == 3) {
//cycle 1
if (current_exec_index == 0) {
//pop return addr low.
- pop();
- return TRUE;
+ return pop();
}
//cycle 2
else if (current_exec_index == 1) {
//cycle 3
else if (current_exec_index == 2) {
//pop return addr hi.
- pop();
- return TRUE;
+ return pop();
}
//cycle 4
else if (current_exec_index == 3) {
int execute6502(void) {
int ret;
ret = current_inst->func();
+ if (!ret && !bus_status) {
+ //if bus status not ready, deson't do anything.
+ return TRUE;
+ }
current_exec_index++;
#ifdef cycle_check
}
int reset_exec6502(void) {
+ if ((bus_status = bus_ready()) != TRUE) {
+ //on reset, if bus is not ready, do nothing.
+ return TRUE;
+ }
+
switch (current_exec_index++) {
case 0:
//step 1: load intvec low.
}
int nmi6502(void) {
+ if ((bus_status = bus_ready()) != TRUE) {
+ //on nmi, if bus is not ready, do nothing.
+ return TRUE;
+ }
+
//dprint("nmi...\n");
//nmi6502 is always called when current instruction execution is done.
switch (current_exec_index++) {
case 0:
//first: push pc hi.
- push(cpu_reg.pc >> 8);
- return TRUE;
+ return push(cpu_reg.pc >> 8);
case 1:
//second: push pc low.
- push(cpu_reg.pc);
- return TRUE;
+ return push(cpu_reg.pc);
case 2:
{
//step 3, push status_reg
unsigned char stat;
memcpy(&stat, &cpu_reg.status, sizeof(stat));
- push(stat);
- return TRUE;
+ return push(stat);
}
case 3:
//step 4: load intvec low.
#include "tools.h"
+#include "sprite.h"
+#include "clock.h"
+#include "bus.h"
-static unsigned char sprite_dma_reg;
+#define DMA_ADDR_MULTIPLE 0x100
+
+void spr_ram_tbl_set(unsigned short offset, unsigned char data);
+
+static unsigned short dma_ram_addr;
+static unsigned char dma_ram_data;
+static unsigned char dma_spr_addr;
+static int start_dma;
+static int dma_cnt;
+
+static void get_ram_data(void) {
+ if (dma_cnt > 0)
+ release_bus();
+ set_rw_pin(0);
+ set_bus_addr(dma_ram_addr++);
+ start_bus();
+ dma_ram_data = get_bus_data();
+ end_bus();
+
+ /*
+ dprint("dma %d, ram:%02x @%04x\n",
+ dma_cnt, dma_ram_data, dma_ram_addr);
+ */
+
+ //keep the bus ownership.
+ take_bus();
+}
+
+static void copy_data(void) {
+
+ if (dma_cnt % 2 == 0) {
+ //load ram value
+ get_ram_data();
+
+ }
+ else {
+ //store into sprite ram
+ spr_ram_tbl_set(dma_spr_addr++, dma_ram_data);
+ }
+
+ if (dma_cnt == SPRITE_RAM_SIZE * 2 - 1) {
+ release_bus();
+ start_dma = FALSE;
+ }
+ dma_cnt++;
+}
+
+/*
+ * clock handler.
+ * */
+static int clock_dma(void) {
+ if (start_dma) {
+ copy_data();
+ }
+
+ return TRUE;
+}
void set_dma_data(unsigned char data) {
- dprint("set_dma_data: %02x\n", data);
- sprite_dma_reg = data;
+ //dprint("set_dma_data: %02x\n", data);
+ dma_ram_addr = data * DMA_ADDR_MULTIPLE;
+ dma_spr_addr = 0;
+ start_dma = TRUE;
+ dma_cnt = 0;
}
int init_dma(void) {
+ int ret;
+
+ dma_ram_addr = 0;
+ dma_spr_addr = 0;
+ dma_ram_data = 0;
+ start_dma = FALSE;
+ dma_cnt = 0;
+
+ ret = register_clock_hander(clock_dma);
+ if (!ret) {
+ return FALSE;
+ }
- sprite_dma_reg = 0;
return TRUE;
}