Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Huffman committed Mar 20, 2018
0 parents commit c57f5c1
Show file tree
Hide file tree
Showing 33 changed files with 10,826 additions and 0 deletions.
694 changes: 694 additions & 0 deletions 6510.c

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions 6510.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* 6510.h - processor emulation for C64 emulator */
/* by Brian Huffman 11-29-00 */

//void cpu6510_main (int cycles);
void cpu6510_main (void);

void cpu6510_reset (void);
void cpu6510_irq (void);
void cpu6510_nmi (void);
void cpu6510_brk (void);

void print_state (void);

void cpu6510_bad_line (void);

void cpu6510_callback (int source, void (*callback)(void), int time);
int cpu6510_clock (void);

enum {
CB_NONE,
CB_MAIN,
CB_RASTER,
CB_REDRAW,
CB_FRAME,
CB_TIMER1A,
CB_TIMER1B,
CB_MAX
};
/*
typedef struct CPUState {
// processor registers
// 16-bit: pc
// 8-bit: a,x,y,s,p
// 1-bit: c,z,i,d,b,v,n
int reg_pc;
int reg_a;
int reg_x;
int reg_y;
int reg_s;
int reg_p;
int flag_n;
int flag_z;
int flag_c;
// cycle counter
int clock;
} CPUState;
*/













79 changes: 79 additions & 0 deletions 6510_addressing.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* 6510_addressing.c - inline functions for 6510 addressing modes */
/* this file is included directly into 6510.c */

/* immediate mode */
inline int addr_imm() {
return reg_pc++;
}

/* zero page */
inline int addr_zpg() {
return mem_read(reg_pc++);
}

/* absolute */
inline int addr_abs() {
int address = mem_read_16(reg_pc);
reg_pc+=2;
return address;
}

/* zero page, x */
inline int addr_zpx() {
int address = mem_read(reg_pc++) + reg_x;
return (address &= 0xff);
}

/* zero page, y */
inline int addr_zpy() {
int address = mem_read(reg_pc++) + reg_y;
return (address &= 0xff);
}

/* absolute, x */
inline int addr_abx() {
int address = mem_read(reg_pc++) + reg_x;

/* test for page boundary crossing */
if (address > 0xff) clock_advance(1);

return address + (mem_read(reg_pc++) << 8);
}

/* absolute, y */
inline int addr_aby() {
int address = mem_read(reg_pc++) + reg_y;

/* test for page boundary crossing */
if (address > 0xff) clock_advance(1);

return address + (mem_read(reg_pc++) << 8);
}

/* indexed indirect */
inline int addr_inx() {
int index = mem_read(reg_pc++) + reg_x;
index &= 0xff;
return mem_read_16(index);
}

/* indirect indexed */
inline int addr_iny() {
int index, address;

index = mem_read(reg_pc++);
address = mem_read(index) + reg_y;

/* test for page boundary crossing */
if (address > 0xff) clock_advance(1);

return address + (mem_read(index + 1) << 8);
}

/* absolute indirect */
inline int addr_ind() {
int index = mem_read_16(reg_pc);
reg_pc += 2;
return mem_read_16(index);
}

114 changes: 114 additions & 0 deletions 6510_highlevel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* highlevel.c - optimized routines for often-called sections of kernal */
/* this file should be included directly into 6510.c */

#include "serial.h"

inline static void update_nz(int result) {
flag_nz = result;
}

/* poll keyboard buffer */
inline void kernal_e5cd() {
/*
e5cd: LDA $c6 ;a5c6 ;NDX no. of chars in keyboard queue
e5cf: STA $cc ;85cc ;BLNSW cursor blink enable, 0=blink
e5d1: STA $0292 ;8d9202 ;AUTODN automatic scroll down, 0=ON
e5d4: BEQ $e5cd ;f0f7 ;loop until keys are pressed
*/

reg_a = mem_read(0xc6);
mem_write(0xcc, reg_a);
mem_write(0x0292, reg_a);
update_nz(reg_a);
if (reg_a==0) { reg_pc = 0xe5cd; clock_advance(1); }
else reg_pc = 0xe5d6;
clock_advance(3+3+4+2);
}

inline void kernal_e9d4() {
int address;
/*
e9d4: LDA ($ac),Y ;b1ac ;SAL screen scrolling ptr
e9d6: STA ($d1),Y ;91d1 ;PNT screen address ptr
e9d8: LDA ($ae),Y ;b1ae ;EAL color scrolling ptr
e9da: STA ($f3),Y ;91f3 ;USER color address ptr
e9dc: DEY ;88
e9dd: BPL $e9d4 ;10f5 ;loop to copy entire line
*/
address = mem_read(0xac) + reg_y;
if (address > 0xff) clock_advance(1);
address += (mem_read(0xad) << 8);
reg_a = mem_read(address);

address = mem_read_16(0xd1) + reg_y;
mem_write (address, reg_a);

address = mem_read(0xae) + reg_y;
if (address > 0xff) clock_advance(1);
address += (mem_read(0xaf) << 8);
reg_a = mem_read(address);

address = mem_read_16(0xf3) + reg_y;
mem_write (address, reg_a);

reg_y = (reg_y - 1) & 0xff;
update_nz(reg_y);
if ( !(reg_p & N_FLAG) ) { reg_pc = 0xe9d4; clock_advance(1); }
else reg_pc = 0xe9df;
clock_advance(5+6+5+6+2+2);
}
/*
eab3: LSR ;4a ;check next row
...
ead2: BNE $eab3 ;d0df ;loop to all rows
*/


/*
fd6c: INC $c2 ;e6c2
...
fd86: BEQ $fd6c ;f0e4 ;loop to check all pages
*/

/*****************************************/
/**** serial emulation kernal patches ****/
/*****************************************/

/* LISTN */
/* SECND */
/* TALK */
/* TKSA */
/* CIOUT */
inline void kernal_ed40() {
int atn, error;

atn = mem_read(0xdd00) & 0x08;

/* $95 = BSOUT, buffered serial char */
error = serial_write (atn, mem_read(0x95));

if (error == SERIAL_DEVICE_NOT_PRESENT) mem_write(0x90, mem_read(0x90) | 0x80);
if (error == SERIAL_TIME_OUT) mem_write(0x90, mem_read(0x90) | 0x03);
cpu6510_CLI();
cpu6510_RTS();
}

/* ACPTR */
inline void kernal_ee13() {
int result = serial_read ();
if (result & SERIAL_END_OF_FILE) mem_write (0x90, mem_read(0x90) | 0x40);
if (result == SERIAL_TIME_OUT) mem_write (0x90, mem_read(0x90) | 0x02);

reg_a = result & 0xff;
cpu6510_CLI();
cpu6510_CLC();
cpu6510_RTS();
}

inline void do_highlevel() {
if (reg_pc == 0xe5cd + 1) kernal_e5cd();
else if (reg_pc == 0xe9d4 + 1) kernal_e9d4();
else if (reg_pc == 0xed40 + 1) kernal_ed40();
else if (reg_pc == 0xee13 + 1) kernal_ee13();
else cpu6510_JAM();
}
Loading

0 comments on commit c57f5c1

Please sign in to comment.