diff --git a/apple1 b/apple1 new file mode 100755 index 0000000..c007a81 Binary files /dev/null and b/apple1 differ diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..6fc22eb --- /dev/null +++ b/build.sh @@ -0,0 +1,20 @@ +SRC_FOLDER="src" +OBJ_FOLDER="obj" +EXEC_NAME="apple1" + +# clear any previous object +rm -rf $OBJ_FOLDER +rm -f $EXEC_NAME + +# build all source code +for FILE in $SRC_FOLDER/*.c +do + cc -c $FILE +done + +# move all objects to appropriate folder +mkdir -p $OBJ_FOLDER +mv *.o $OBJ_FOLDER + +# create executable out of the objects +cc -o $EXEC_NAME $OBJ_FOLDER/*.o diff --git a/obj/6502.o b/obj/6502.o new file mode 100644 index 0000000..48757f7 Binary files /dev/null and b/obj/6502.o differ diff --git a/obj/main.o b/obj/main.o new file mode 100644 index 0000000..4c55c17 Binary files /dev/null and b/obj/main.o differ diff --git a/obj/memory.o b/obj/memory.o new file mode 100644 index 0000000..e1b1140 Binary files /dev/null and b/obj/memory.o differ diff --git a/obj/opcodes.o b/obj/opcodes.o new file mode 100644 index 0000000..9b4b39a Binary files /dev/null and b/obj/opcodes.o differ diff --git a/obj/ram.o b/obj/ram.o new file mode 100644 index 0000000..be62b84 Binary files /dev/null and b/obj/ram.o differ diff --git a/obj/rom.o b/obj/rom.o new file mode 100644 index 0000000..5d4f100 Binary files /dev/null and b/obj/rom.o differ diff --git a/src/6502.c b/src/6502.c new file mode 100644 index 0000000..211d5a2 --- /dev/null +++ b/src/6502.c @@ -0,0 +1,176 @@ +#include "inc/types.h" +#include "inc/memory.h" +#include "inc/opcodes.h" + +oc1 opcode_decoded_1; +oc2 opcode_decoded_2; + +void init() +{ + // pc is set using 0xFFFC-0xFFFD + mem.mar = 0xFFFD; + mem_read(); + pc = mem.mdr << 8; + mem.mar = 0xFFFC; + mem_read(); + pc = mem.mdr + pc; +} + +void fetch() +{ + mem.mar = pc; + mem_read(); + ir = mem.mdr; + pc++; +} + +void decode() +{ + // instruction pattern is "aaabbbccc" where: + // aaa cc determines the opcode + // bbb determines the addressing mode + + db aaa = (ir & 0b11100000) >> 5; + db bbb = (ir & 0b00011100) >> 2; + db cc = (ir & 0b00000011); + + db aaacc = (aaa << 2) | cc; + + opcode_decoded_1 = aaacc; + opcode_decoded_2 = ir; +} + +void execute() +{ + switch(opcode_decoded_2) + { + case BRK: + return brk(); + case BPL: + return bpl(); + case JSR: + return jsr(); + case BMI: + return bmi(); + case RTI: + return rti(); + case BVC: + return bvc(); + case RTS: + return rts(); + case BVS: + return bvs(); + case BCC: + return bcc(); + case BCS: + return bcs(); + case BNE: + return bne(); + case BEQ: + return beq(); + case PHP: + return php(); + case CLC: + return clc(); + case PLP: + return plp(); + case SEC: + return sec(); + case PHA: + return pha(); + case CLI: + return cli(); + case PLA: + return pla(); + case SEI: + return sei(); + case DEY: + return dey(); + case TYA: + return tya(); + case TAY: + return tay(); + case CLV: + return clv(); + case INY: + return iny(); + case CLD: + return cld(); + case INX: + return inx(); + case SED: + return sed(); + case TXA: + return txa(); + case TXS: + return txs(); + case TAX: + return tax(); + case TSX: + return tsx(); + case DEX: + return dex(); + case NOP: + return nop(); + } + + switch (opcode_decoded_1) + { + case BIT: + return bit(); + case JMP: + return jmp(); + case JPA: // JMP (absolute) + return jmp(); + case STY: + return sty(); + case LDY: + return ldy(); + case CPY: + return cpy(); + case CPX: + return cpx(); + case ORA: + return ora(); + case AND: + return and(); + case EOR: + return eor(); + case ADC: + return adc(); + case STA: + return sta(); + case LDA: + return lda(); + case CMP: + return cmp(); + case SBC: + return sbc(); + case ASL: + return asl(); + case ROL: + return rol(); + case LSR: + return lsr(); + case ROR: + return ror(); + case STX: + return stx(); + case LDX: + return ldx(); + case DEC: + return dec(); + case INC: + return inc(); + } +} + +void run() +{ + while (pc != 0) + { + fetch(); + decode(); + execute(); + } +} diff --git a/src/inc/6502.h b/src/inc/6502.h new file mode 100644 index 0000000..9ebeba1 --- /dev/null +++ b/src/inc/6502.h @@ -0,0 +1,7 @@ +#ifndef _APPLE_I_6502_H_ +#define _APPLE_I_6502_H_ + +void init(); +void run(); + +#endif diff --git a/src/inc/memory.h b/src/inc/memory.h new file mode 100644 index 0000000..5722ee0 --- /dev/null +++ b/src/inc/memory.h @@ -0,0 +1,11 @@ +#ifndef _APPLE_I_MEMORY_LOGIC_H_ +#define _APPLE_I_MEMORY_LOGIC_H_ + +#include "types.h" + +mr mem; // memory "glue" logic + +void mem_read(); +void mem_write(); + +#endif diff --git a/src/inc/opcodes.h b/src/inc/opcodes.h new file mode 100644 index 0000000..c2252ea --- /dev/null +++ b/src/inc/opcodes.h @@ -0,0 +1,142 @@ +#ifndef _APPLE_I_OPCODES_H_ +#define _APPLE_I_OPCODES_H_ + +#include "types.h" + +dw pc; // program counter +db ac; // accumulator +db x; // x register +db y; // y register +db sp; // stack pointer +db ir; // intruction register + +enum opcodes +{ + BIT = 0b00100, + JMP = 0b01000, + JPA = 0b01100, + STY = 0b10000, + LDY = 0b10100, + CPY = 0b11000, + CPX = 0b11100, + + ORA = 0b00001, + AND = 0b00101, + EOR = 0b01001, + ADC = 0b01101, + STA = 0b10001, + LDA = 0b10101, + CMP = 0b11001, + SBC = 0b11101, + + ASL = 0b00010, + ROL = 0b00110, + LSR = 0b01010, + ROR = 0b01110, + STX = 0b10010, + LDX = 0b10110, + DEC = 0b11010, + INC = 0b11110, +}; + +enum opcodes_comp +{ + BRK = 0x00, + BPL = 0x10, + JSR = 0x20, + BMI = 0x30, + RTI = 0x40, + BVC = 0x50, + RTS = 0x60, + BVS = 0x70, + BCC = 0x90, + BCS = 0xB0, + BNE = 0xD0, + BEQ = 0xF0, + + PHP = 0x08, + CLC = 0x18, + PLP = 0x28, + SEC = 0x38, + PHA = 0x48, + CLI = 0x58, + PLA = 0x68, + SEI = 0x78, + DEY = 0x88, + TYA = 0x98, + TAY = 0xA8, + CLV = 0xB8, + INY = 0xC8, + CLD = 0xD8, + INX = 0xE8, + SED = 0xF8, + + TXA = 0x8A, + TXS = 0x9A, + TAX = 0xAA, + TSX = 0xBA, + DEX = 0xCA, + NOP = 0xEA +}; + +typedef enum opcodes oc1; +typedef enum opcodes_comp oc2; + +void adc(); // add memory to accumalator with carry +void and(); // and memory with accumulator +void asl(); // shift left one bit (memory on accumulator) +void bcc(); // branch on carry clear +void bcs(); // branch on carry set +void beq(); // branch on result zero +void bit(); // test bits in memory with accumulator +void bmi(); // branch on result minus +void bne(); // branch on result not zero +void bpl(); // branch on result plus +void brk(); // force break +void bvc(); // branch on overflow clear +void bvs(); // branch on overflow set +void clc(); // clear carry flag +void cld(); // clear decimal mode +void cli(); // clear interrupt disable bit +void clv(); // clear overflow flag +void cmp(); // compare memory with accumulator +void cpx(); // compare memory and index x +void cpy(); // compare memory and index y +void dec(); // decrement memory by one +void dex(); // decrement index x by one +void dey(); // decrement index y by one +void eor(); // exclusive-or memory with accumulator +void inc(); // increment memory by one +void inx(); // increment index x by one +void iny(); // increment index y by one +void jmp(); // jump to new location +void jsr(); // jump to new location saving return address +void lda(); // load accumulator with memory +void ldx(); // load index x with memory +void ldy(); // load index y with memory +void lsr(); // shift one bit right (memory or accumulator) +void nop(); // no operation +void ora(); // or memory with accumulator +void pha(); // push accumulator on stack +void php(); // push processor status on stack +void pla(); // pull accumulator from stack +void plp(); // pull processor status from stack +void rol(); // rotate on bit left (memory or accumulator) +void ror(); // rotate on bit right (memory or accumulator) +void rti(); // return from interrupt +void rts(); // retrun from subroutine +void sbc(); // subtract memory from accumulator with borrow +void sec(); // set carry flag +void sed(); // set decimal flag +void sei(); // set interrupt disable status +void sta(); // store accumulator in memory +void stx(); // store index x in memory +void sty(); // store index y in memory +void tax(); // transfer accumulator to index x +void tay(); // transfer accumulator to index y +void tsx(); // transfer stack pointer to index x +void txa(); // transfer index x to accumulator +void txs(); // transfer index x to stack pointer +void tya(); // transfer index y to accumulator + +#endif diff --git a/src/inc/ram.h b/src/inc/ram.h new file mode 100644 index 0000000..79c4f3d --- /dev/null +++ b/src/inc/ram.h @@ -0,0 +1,11 @@ +#ifndef _APPLE_I_RAM_H_ +#define _APPLE_I_RAM_H_ + +#include "types.h" + +mr ram; // random access memory + +void ram_read(); +void ram_write(); + +#endif diff --git a/src/inc/rom.h b/src/inc/rom.h new file mode 100644 index 0000000..db3e3e1 --- /dev/null +++ b/src/inc/rom.h @@ -0,0 +1,10 @@ +#ifndef _APPLE_I_ROM_H_ +#define _APPLE_I_ROM_H_ + +#include "types.h" + +mr rom; // read only memory + +void rom_read(); + +#endif diff --git a/src/inc/types.h b/src/inc/types.h new file mode 100644 index 0000000..d822094 --- /dev/null +++ b/src/inc/types.h @@ -0,0 +1,16 @@ +#ifndef _APPLE_I_TYPES_H_ +#define _APPLE_I_TYPES_H_ + +typedef unsigned char db; +typedef unsigned short dw; +typedef unsigned int dd; + +struct memory_registers +{ + dw mar; // memory address register + db mdr; // memory data register +}; + +typedef struct memory_registers mr; + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..32ce5d6 --- /dev/null +++ b/src/main.c @@ -0,0 +1,11 @@ +#include + +#include "inc/6502.h" + +int main(int argc, char **argv) +{ + printf("Apple-I Computer\n"); + init(); + run(); + return 0; +} diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..3529595 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,65 @@ +#include "inc/types.h" +#include "inc/ram.h" +#include "inc/rom.h" +#include "inc/memory.h" + +/* + + + - - - - + + | 0000 | + | | + | | + | RAM | + | | + | | + | 0FFF | + + - - - - + + | | + + . . . + unused + . . . + + | | + + - - - - + + | FF00 | + | | + | ROM | + | | + | FFFF | + + - - - - + + + */ + +void mem_read() +{ + if (mem.mar >= 0x0000 && mem.mar <= 0x0FFF) + { + // 4KB memory RAM + ram.mar = mem.mar; + ram_read(); + mem.mdr = ram.mdr; + } + else if (mem.mar >= 0xFF00 && mem.mar <= 0xFFFF) + { + // wozmon ROM + rom.mar = mem.mar & 0x00FF; + rom_read(); + mem.mdr = rom.mdr; + } + else + { + mem.mdr = 0x00; + } +} + +void mem_write() +{ + if (mem.mar >= 0x0000 && mem.mar <= 0x0FFF) + { + // 4KB memory RAM + ram.mar = mem.mar; + ram.mdr = mem.mdr; + ram_write(); + } +} diff --git a/src/opcodes.c b/src/opcodes.c new file mode 100644 index 0000000..4e01603 --- /dev/null +++ b/src/opcodes.c @@ -0,0 +1,339 @@ +#include + +#include "inc/opcodes.h" + +void adc() +{ + // add memory to accumalator with carry + printf("ADC\n"); +} + +void and() +{ + // and memory with accumulator + printf("AND\n"); +} + +void asl() +{ + // shift left one bit (memory on accumulator) + printf("ASL\n"); +} + +void bcc() +{ + // branch on carry clear + printf("BCC\n"); +} + +void bcs() +{ + // branch on carry set + printf("BSC\n"); +} + +void beq() +{ + // branch on result zero + printf("BEQ\n"); +} + +void bit() +{ + // test bits in memory with accumulator + printf("BIT\n"); +} + +void bmi() +{ + // branch on result minus + printf("BMI\n"); +} + +void bne() +{ + // branch on result not zero + printf("BNE\n"); +} + +void bpl() +{ + // branch on result plus + printf("BPL\n"); +} + +void brk() +{ + // force break + printf("BRK\n"); +} + +void bvc() +{ + // branch on overflow clear + printf("BVC\n"); +} + +void bvs() +{ + // branch on overflow set + printf("BVS\n"); +} + +void clc() +{ + // clear carry flag + printf("CLC\n"); +} + +void cld() +{ + // clear decimal mode + printf("CLD\n"); +} + +void cli() +{ + // clear interrupt disable bit + printf("CLI\n"); +} + +void clv() +{ + // clear overflow flag + printf("CLV\n"); +} + +void cmp() +{ + // compare memory with accumulator + printf("CMP\n"); +} + +void cpx() +{ + // compare memory and index x + printf("CPX\n"); +} + +void cpy() +{ + // compare memory and index y + printf("CPY\n"); +} + +void dec() +{ + // decrement memory by one + printf("DEC\n"); +} + +void dex() +{ + // decrement index x by one + printf("DEX\n"); +} + +void dey() +{ + // decrement index y by one + printf("DEY\n"); +} + +void eor() +{ + // exclusive-or memory with accumulator + printf("EOR\n"); +} + +void inc() +{ + // increment memory by one + printf("INC\n"); +} + +void inx() +{ + // increment index x by one + printf("INX\n"); +} + +void iny() +{ + // increment index y by one + printf("INY\n"); +} + +void jmp() +{ + // jump to new location + printf("JMP\n"); +} + +void jsr() +{ + // jump to new location saving return address + printf("JSR\n"); +} + +void lda() +{ + // load accumulator with memory + printf("LDA\n"); +} + +void ldx() +{ + // load index x with memory + printf("LDX\n"); +} + +void ldy() +{ + // load index y with memory + printf("LDY\n"); +} + +void lsr() +{ + // shift one bit right (memory or accumulator) + printf("LSR\n"); +} + +void nop() +{ + // no operation + printf("NOP\n"); +} + +void ora() +{ + // or memory with accumulator + printf("ORA\n"); +} + +void pha() +{ + // push accumulator on stack + printf("PHA\n"); +} + +void php() +{ + // push processor status on stack + printf("PHP\n"); +} + +void pla() +{ + // pull accumulator from stack + printf("PLA\n"); +} + +void plp() +{ + // pull processor status from stack + printf("PLP\n"); +} + +void rol() +{ + // rotate on bit left (memory or accumulator) + printf("ROL\n"); +} + +void ror() +{ + // rotate on bit right (memory or accumulator) + printf("ROR\n"); +} + +void rti() +{ + // return from interrupt + printf("RTI\n"); +} + +void rts() +{ + // retrun from subroutine + printf("RTS\n"); +} + +void sbc() +{ + // subtract memory from accumulator with borrow + printf("SBC\n"); +} + +void sec() +{ + // set carry flag + printf("SEC\n"); +} + +void sed() +{ + // set decimal flag + printf("SED\n"); +} + +void sei() +{ + // set interrupt disable status + printf("SEI\n"); +} + +void sta() +{ + // store accumulator in memory + printf("STA\n"); +} + +void stx() +{ + // store index x in memory + printf("STX\n"); +} + +void sty() +{ + // store index y in memory + printf("STY\n"); +} + +void tax() +{ + // transfer accumulator to index x + printf("TAX\n"); +} + +void tay() +{ + // transfer accumulator to index y + printf("TAY\n"); +} + +void tsx() +{ + // transfer stack pointer to index x + printf("TSX\n"); +} + +void txa() +{ + // transfer index x to accumulator + printf("TXA\n"); +} + +void txs() +{ + // transfer index x to stack pointer + printf("TXS\n"); +} + +void tya() +{ + // transfer index y to accumulator + printf("TYA\n"); +} diff --git a/src/ram.c b/src/ram.c new file mode 100644 index 0000000..d95f1af --- /dev/null +++ b/src/ram.c @@ -0,0 +1,14 @@ +#include "inc/types.h" +#include "inc/ram.h" + +db ram_memory[4096]; // total memory: 4KB + +void ram_read() +{ + ram.mdr = ram_memory[ram.mar]; +} + +void ram_write() +{ + ram_memory[ram.mar] = ram.mdr; +} diff --git a/src/rom.c b/src/rom.c new file mode 100644 index 0000000..5015dc5 --- /dev/null +++ b/src/rom.c @@ -0,0 +1,42 @@ +#include "inc/types.h" +#include "inc/rom.h" + +db rom_memory[] = { + 0xD8, 0x58, 0xA0, 0x7F, 0x8C, 0x12, 0xD0, 0xA9, + 0xA7, 0x8D, 0x11, 0xD0, 0x8D, 0x13, 0xD0, 0xC9, + 0xDF, 0xF0, 0x13, 0xC9, 0x9B, 0xF0, 0x03, 0xC8, + 0x10, 0x0F, 0xA9, 0xDC, 0x20, 0xEF, 0xFF, 0xA9, + 0x8D, 0x20, 0xEF, 0xFF, 0xA0, 0x01, 0x88, 0x30, + 0xF6, 0xAD, 0x11, 0xD0, 0x10, 0xFB, 0xAD, 0x10, + 0xD0, 0x99, 0x00, 0x02, 0x20, 0xEF, 0xFF, 0xC9, + 0x8D, 0xD0, 0xD4, 0xA0, 0xFF, 0xA9, 0x00, 0xAA, + 0x0A, 0x85, 0x2B, 0xC8, 0xB9, 0x00, 0x02, 0xC9, + 0x8D, 0xF0, 0xD4, 0xC9, 0xAE, 0x90, 0xF4, 0xF0, + 0xF0, 0xC9, 0xBA, 0xF0, 0xEB, 0xC9, 0xD2, 0xF0, + 0x3B, 0x86, 0x28, 0x86, 0x29, 0x84, 0x2A, 0xB9, + 0x00, 0x02, 0x49, 0xB0, 0xC9, 0x0A, 0x90, 0x06, + 0x69, 0x88, 0xC9, 0xFA, 0x90, 0x11, 0x0A, 0x0A, + 0x0A, 0x0A, 0xA2, 0x04, 0x0A, 0x26, 0x28, 0x26, + 0x29, 0xCA, 0xD0, 0xF8, 0xC8, 0xD0, 0xE0, 0xC4, + 0x2A, 0xF0, 0x97, 0x24, 0x2B, 0x50, 0x10, 0xA5, + 0x28, 0x81, 0x26, 0xE6, 0x26, 0xD0, 0xB5, 0xE6, + 0x27, 0x4C, 0x44, 0xFF, 0x6C, 0x24, 0x00, 0x30, + 0x2B, 0xA2, 0x02, 0xB5, 0x27, 0x95, 0x25, 0x95, + 0x23, 0xCA, 0xD0, 0xF7, 0xD0, 0x14, 0xA9, 0x8D, + 0x20, 0xEF, 0xFF, 0xA5, 0x25, 0x20, 0xDC, 0xFF, + 0xA5, 0x24, 0x20, 0xDC, 0xFF, 0xA9, 0xBA, 0x20, + 0xEF, 0xFF, 0xA9, 0xA0, 0x20, 0xEF, 0xFF, 0xA1, + 0x24, 0x20, 0xDC, 0xFF, 0x86, 0x2B, 0xA5, 0x24, + 0xC5, 0x28, 0xA5, 0x25, 0xE5, 0x29, 0xB0, 0xC1, + 0xE6, 0x24, 0xD0, 0x02, 0xE6, 0x25, 0xA5, 0x24, + 0x29, 0x07, 0x10, 0xC8, 0x48, 0x4A, 0x4A, 0x4A, + 0x4A, 0x20, 0xE5, 0xFF, 0x68, 0x29, 0x0F, 0x09, + 0xB0, 0xC9, 0xBA, 0x90, 0x02, 0x69, 0x06, 0x2C, + 0x12, 0xD0, 0x30, 0xFB, 0x8D, 0x12, 0xD0, 0x60, + 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, 0x00, 0x00 +}; + +void rom_read() +{ + rom.mdr = rom_memory[rom.mar]; +}