commit b66ddfb4a8692757f7887788d3a41a413b9567d8 Author: Ruthenic Date: Tue May 24 16:54:33 2022 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..14fb13d --- /dev/null +++ b/LICENSE @@ -0,0 +1,3 @@ +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9a99972 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +CC ?= gcc +target ?= $(shell ${CC} -dumpmachine) +CC_FLAGS ?= +CC_FLAGS := ${CC_FLAGS} -Ilib +DESTDIR ?= / + +.PHONY: all debug clean build-release install +all: + @$(shell mkdir -p bin) +all: main + +main: + @${CC} -o bin/main src/main.c ${CC_FLAGS} + +debug: CC_FLAGS:=-g -O0 -v -fsanitize=undefined -fsanitize=address ${CC_FLAGS} +debug: all + +clean: + @rm -rf bin + +release: CC_FLAGS:=-O3 ${CC_FLAGS} +release: all +release: + @strip bin/* + tar -czf release.tar.gz bin/* + +install: + @install -m 777 bin/main ${DESTDIR}/usr/local/bin diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..7784424 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,2 @@ +-Ilib +-DDRAKECU_VERSION="placeholder" diff --git a/examples/as65 b/examples/as65 new file mode 100755 index 0000000..67af97b Binary files /dev/null and b/examples/as65 differ diff --git a/examples/bubble.asm b/examples/bubble.asm new file mode 100644 index 0000000..fe08466 --- /dev/null +++ b/examples/bubble.asm @@ -0,0 +1,42 @@ +;THIS SUBROUTINE ARRANGES THE 8-BIT ELEMENTS OF A LIST IN ASCENDING +;ORDER. THE STARTING ADDRESS OF THE LIST IS IN LOCATIONS $30 AND +;$31. THE LENGTH OF THE LIST IS IN THE FIRST BYTE OF THE LIST. LOCATION +;$32 IS USED TO HOLD AN EXCHANGE FLAG. + lda #$05 + sta $30 + sta $33 + lda #$A4 + sta $34 + lda #$07 + sta $35 + lda #$F6 + sta $36 + lda #$44 + lda $37 + +SORT8 ldy #$00 ;TURN EXCHANGE FLAG OFF (= 0) + sty $32 + lda ($30),Y ;FETCH ELEMENT COUNT + tax ; AND PUT IT INTO X + iny ;POINT TO FIRST ELEMENT IN LIST + dex ;DECREMENT ELEMENT COUNT +NXTEL lda ($30),Y ;FETCH ELEMENT + iny + cmp ($30),Y ;IS IT LARGER THAN THE NEXT ELEMENT? + bcc CHKEND + beq CHKEND + ;YES. EXCHANGE ELEMENTS IN MEMORY + pha ; BY SAVING LOW BYTE ON STACK. + lda ($30),Y ; THEN GET HIGH BYTE AND + dey ; STORE IT AT LOW ADDRESS + sta ($30),Y + pla ;PULL LOW BYTE FROM STACK + iny ; AND STORE IT AT HIGH ADDRESS + sta ($30),Y + lda #$FF ;TURN EXCHANGE FLAG ON (= -1) + sta $32 +CHKEND dex ;END OF LIST? + bne NXTEL ;NO. FETCH NEXT ELEMENT + bit $32 ;YES. EXCHANGE FLAG STILL OFF? + bmi SORT8 ;NO. GO THROUGH LIST AGAIN + rts ;YES. LIST IS NOW ORDERED diff --git a/examples/hi.asm b/examples/hi.asm new file mode 100644 index 0000000..4dcf370 --- /dev/null +++ b/examples/hi.asm @@ -0,0 +1,4 @@ + inc $00E7 + inc $0001 + inx + iny diff --git a/examples/make.sh b/examples/make.sh new file mode 100755 index 0000000..3f378fb --- /dev/null +++ b/examples/make.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +mkdir -p bin + +for i in *.asm +do + xa -v -o bin/`echo $i | sed "s/.asm/.bin/g"` -l bin/`echo $i | sed "s/.asm/.lst/g"` $i +done diff --git a/lib/constants.h b/lib/constants.h new file mode 100644 index 0000000..33289fb --- /dev/null +++ b/lib/constants.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include + +uint8_t memory[0xFFFF + 1]; //16kib memory (probably) + //0x0000 - 0x00FF is Zero Paged + //0x0100 - 0x01FF is system stack + +uint16_t prc = 0; //16bit program counter + +uint8_t spt = 0; //8bit stack pointer + +uint8_t acc = 0; //8bit accumulator +uint8_t irx,iry = 0; //2 8bit index registers + +struct status { + bool carry; //carry flag + bool zero; //zero flag + bool ird; //interrupt disable flag + bool dec; //decimal mode flag for arithmetic + bool brk; //break bit + bool overflow; //overflow flag + bool neg; //negative flag +}; + + +struct status cpuStatus; diff --git a/lib/file.h b/lib/file.h new file mode 100644 index 0000000..5b2037d --- /dev/null +++ b/lib/file.h @@ -0,0 +1,11 @@ +#include + +int8_t bin[] = { + 0xa9, 0x05, 0x85, 0x30, 0x85, 0x33, 0xa9, 0xa4, 0x85, 0x34, 0xa9, 0x07, + 0x85, 0x35, 0xa9, 0xf6, 0x85, 0x36, 0xa9, 0x44, 0xa5, 0x37, 0xa0, 0x00, + 0x84, 0x32, 0xb1, 0x30, 0xaa, 0xc8, 0xca, 0xb1, 0x30, 0xc8, 0xd1, 0x30, + 0x90, 0x10, 0xf0, 0x0e, 0x48, 0xb1, 0x30, 0x88, 0x91, 0x30, 0x68, 0xc8, + 0x91, 0x30, 0xa9, 0xff, 0x85, 0x32, 0xca, 0xd0, 0xe6, 0x24, 0x32, 0x30, + 0xd9, 0x60 +}; +unsigned int __6502_functional_test_bin_len = 62; diff --git a/src/emu.c b/src/emu.c new file mode 100644 index 0000000..6f6ae41 --- /dev/null +++ b/src/emu.c @@ -0,0 +1,183 @@ +#include "constants.h" + +#include +#include +#include + +void memview() { + for (int i = 0x00; i <= 0xFFFF; i++) { + if (memory[i] != 0x00) { + //printf("Mem Address 0x%04X: 0x%04X\n", i, memory[i]); + } + } + printf("irx - %d\n", irx); + printf("iry - %d\n", iry); + printf("acc - %d\n", acc); +} + +int emulate(uint8_t exec[], int size, uint8_t addr) { + //uint8_t* program = (uint8_t*)exec; + for (int i = addr, i2=0; i < size+addr; i++) { + memory[i] = exec[i2]; + i2++; + } + + while (prc < size) { + uint8_t inst = memory[addr+prc]; + switch (inst) { + //BRK + case 0x00: + cpuStatus.brk = 0x01; + prc++; + prc++; + break; + //NOP + case 0xEA: + prc++; + break; + case 0x80: + prc++; + break; + + //variations on an INC + case 0xE6: + memory[memory[++prc+addr]]++; + prc++; + break; + case 0xE8: + irx++; + prc++; + break; + case 0xC8: + iry++; + prc++; + break; + + //LDA + case 0xA9: { + uint8_t mem = memory[memory[++prc+addr]]; + acc = mem; + prc++; + break; + } + case 0xA5: { + uint8_t mem = memory[memory[++prc+addr]]; + acc = mem; + prc++; + break; + } + case 0xB1: { + uint8_t mem = memory[(++prc)+addr]; + mem+=iry; + acc = memory[mem]; + prc++; + break; + } + + //STA + case 0x85: { + memory[memory[++prc+addr]] = acc; + prc++; + break; + } + + //STY + case 0x84: { + memory[memory[++prc+addr]] = iry; + prc++; + break; + } + + //variations on an LDY (it doesn't work as well the second time) + case 0xA0: { + uint8_t mem = memory[memory[++prc+addr]]; + iry = mem; + prc++; + break; + } + + //ORA + case 0x01: { + uint8_t mem = memory[(++prc)+addr]; + mem+=irx; + uint8_t val = memory[mem]; + acc = acc | val; + prc++; + break; + } + + //TAX + case 0xAA: { + irx = acc; + if (irx == 0) { + cpuStatus.zero = 1; + } else { + cpuStatus.zero = 0; + } + prc++; + break; + } + + //DEX + case 0xCA: { + irx--; + if (irx == 0) { + cpuStatus.zero = 1; + } else { + cpuStatus.zero = 0; + } + prc++; + break; + } + case 0xD1: { + uint8_t mem = memory[(++prc)+addr]; + mem+=iry; + mem = memory[mem]; + if (acc >= mem) { + cpuStatus.carry = 1; + } else { + cpuStatus.carry = 0; + } + + if (acc == mem) { + cpuStatus.zero = 1; + } else { + cpuStatus.zero = 0; + } + prc++; + break; + } + + + case 0x90: { + uint8_t mem = memory[memory[++prc+addr]]; + if (cpuStatus.carry == 0x00) { + prc += mem; + } + break; + } + case 0x10: { + uint8_t mem = memory[memory[++prc+addr]]; + if (cpuStatus.neg == 0x00) { + prc += mem; + } + break; + } + case 0xF0: { + uint8_t mem = memory[memory[++prc+addr]]; + if (cpuStatus.zero == 0x00) { + prc += mem; + } + break; + } + + default: + printf("Opcode 0x%02X\n not implemented!\n", inst); + _exit(0); + } + printf("Ran inst 0x%02X\n", inst); + memview(); + } + + return 0; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a4c0420 --- /dev/null +++ b/src/main.c @@ -0,0 +1,85 @@ +#include "constants.h" +#include "file.h" + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include "emu.c" + +uint16_t* fileRead(char* name) { + FILE* fp = fopen(name, "rb"); + if (!(access(name, F_OK) == 0)) { + errno = -1; + printf("Hi?\n"); + return 0; + } + + struct stat st; + stat(name, &st); + int length = st.st_size; + + uint16_t rbuf[length+1]; + + for (int i = 0; i < length; i++) { + fread(&rbuf[i], 2, 1, fp); + } + fclose(fp); + + uint16_t* tmp = rbuf; + return tmp; +} + +//blanks out memory and initializes various things +int init() { + for (int i = 0; i <= 0xFFFF; i++) { //blank memory + memory[i] = 0x00; + } + + cpuStatus.brk = 0; + cpuStatus.carry = 0; + cpuStatus.dec = 0; + cpuStatus.ird = 0; + cpuStatus.neg = 0; + cpuStatus.overflow = 0; + cpuStatus.zero = 0; + + return 0; +} + +void help(char* exe) { + printf("%s - a 6502 emulator.\n" + " Usage: %s [prg]", exe, exe); +} + +int main(int argc, char* argv[]) { + char* filename = *++argv; //TODO: jankiest thing ever + + /*uint16_t* binary = (uint16_t*)fileRead(filename); + + //uint16_t binary[] = {0xe7e6, 0xeaea, 0x01e6, 0xe8ea, 0xc8ea, 0x00ea}; + int size = sizeof(binary)/sizeof(binary[0])+1; + uint8_t exec[size*2]; + for (int i,i2 = 0; i < size-1; i++) { + printf("%04X\n", binary[i]); + uint8_t lsb = (binary[i] & 0xFF); + uint8_t hsb = (binary[i] & 0xFF00) >> 8; + exec[i2] = lsb; + exec[++i2] = hsb; + i2++; + }*/ + uint8_t* exec = (uint8_t*)bin; + int size = __6502_functional_test_bin_len; + printf("Program ROM:\n"); + for (int i = 0; i < size; i++) { + printf("0x%02X\n", exec[i]); + } + emulate(exec, size, 0x0400); //hacky lol + return 0; +}