Compare commits
No commits in common. "b1ec2bd4e4906b35226bdf07497c7458638ba2f0" and "e8e553e859a835fbff436a9a26f9c67bf6d1a616" have entirely different histories.
b1ec2bd4e4
...
e8e553e859
18
Makefile
18
Makefile
@ -1,25 +1,17 @@
|
|||||||
.ONESHELL:
|
|
||||||
|
|
||||||
CC=gcc
|
|
||||||
CFLAGS=-lcsfml-window -lcsfml-system -lcsfml-graphics
|
CFLAGS=-lcsfml-window -lcsfml-system -lcsfml-graphics
|
||||||
PREFIX=$(HOME)/.local
|
PREFIX=$(HOME)/.local
|
||||||
|
CACHE=$(shell if [ "$$XDG_CACHE_HOME" ]; then echo "$$XDG_CACHE_HOME"; else echo "$$HOME"/.cache; fi)
|
||||||
|
|
||||||
all: ls7emulator
|
all: ls7emulator
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin/ls7emulator bin/
|
rm -f ls7emulator $(CACHE)/ls7emulator
|
||||||
|
|
||||||
ls7emulator:
|
ls7emulator: ls7emulator.c ls7emulator.h config.h
|
||||||
cd src
|
|
||||||
$(CC) ls7emulator.c -o ls7emulator $(CFLAGS)
|
$(CC) ls7emulator.c -o ls7emulator $(CFLAGS)
|
||||||
|
|
||||||
rm ../bin -rf
|
|
||||||
mkdir ../bin
|
|
||||||
cd ../bin
|
|
||||||
mv ../src/ls7emulator ./
|
|
||||||
strip ls7emulator
|
strip ls7emulator
|
||||||
|
|
||||||
install: ls7emulator
|
install: ls7emulator
|
||||||
mkdir -p $(PREFIX)/bin
|
mkdir -p $(PREFIX)/bin
|
||||||
install bin/ls7emulator $(PREFIX)/bin/ls7emulator
|
install ./ls7emulator $(PREFIX)/bin/ls7emulator
|
||||||
cp bin/ls7emulator /usr/bin/ls7emulator
|
cp ./ls7emulator /usr/bin/ls7emulator
|
||||||
|
156
src/cpu.c
156
src/cpu.c
@ -12,6 +12,14 @@ extern uint8_t read6502(uint16_t address);
|
|||||||
extern void write6502(uint16_t address, uint8_t value);
|
extern void write6502(uint16_t address, uint8_t value);
|
||||||
|
|
||||||
//6502 defines
|
//6502 defines
|
||||||
|
#define UNDOCUMENTED //when this is defined, undocumented opcodes are handled.
|
||||||
|
//otherwise, they're simply treated as NOPs.
|
||||||
|
|
||||||
|
//#define NES_CPU //when this is defined, the binary-coded decimal (BCD)
|
||||||
|
//status flag is not honored by ADC and SBC. the 2A03
|
||||||
|
//CPU in the Nintendo Entertainment System does not
|
||||||
|
//support BCD operation.
|
||||||
|
|
||||||
#define FLAG_CARRY 0x01
|
#define FLAG_CARRY 0x01
|
||||||
#define FLAG_ZERO 0x02
|
#define FLAG_ZERO 0x02
|
||||||
#define FLAG_INTERRUPT 0x04
|
#define FLAG_INTERRUPT 0x04
|
||||||
@ -69,17 +77,10 @@ uint8_t sp, a, x, y, status = FLAG_CONSTANT;
|
|||||||
|
|
||||||
|
|
||||||
//helper variables
|
//helper variables
|
||||||
uint32_t clockticks6502 = 0;
|
uint64_t instructions = 0; //keep track of total instructions executed
|
||||||
uint32_t clockgoal6502 = 0;
|
uint32_t clockticks6502 = 0, clockgoal6502 = 0;
|
||||||
|
uint16_t oldpc, ea, reladdr, value, result;
|
||||||
uint16_t oldpc;
|
uint8_t opcode, oldstatus;
|
||||||
uint16_t ea;
|
|
||||||
uint16_t reladdr;
|
|
||||||
uint16_t value;
|
|
||||||
uint16_t result;
|
|
||||||
|
|
||||||
uint8_t opcode;
|
|
||||||
uint8_t oldstatus;
|
|
||||||
|
|
||||||
//a few general functions used by various other functions
|
//a few general functions used by various other functions
|
||||||
void push16(uint16_t pushval) {
|
void push16(uint16_t pushval) {
|
||||||
@ -156,7 +157,7 @@ static void absx() { //absolute,X
|
|||||||
startpage = ea & 0xFF00;
|
startpage = ea & 0xFF00;
|
||||||
ea += (uint16_t)x;
|
ea += (uint16_t)x;
|
||||||
|
|
||||||
if (startpage != (ea & 0xFF00)) { //one cycle penalty for page-crossing on some opcodes
|
if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
|
||||||
penaltyaddr = 1;
|
penaltyaddr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,6 +226,22 @@ static void adc() {
|
|||||||
overflowcalc(result, a, value);
|
overflowcalc(result, a, value);
|
||||||
signcalc(result);
|
signcalc(result);
|
||||||
|
|
||||||
|
#ifndef NES_CPU
|
||||||
|
if (status & FLAG_DECIMAL) {
|
||||||
|
clearcarry();
|
||||||
|
|
||||||
|
if ((a & 0x0F) > 0x09) {
|
||||||
|
a += 0x06;
|
||||||
|
}
|
||||||
|
if ((a & 0xF0) > 0x90) {
|
||||||
|
a += 0x60;
|
||||||
|
setcarry();
|
||||||
|
}
|
||||||
|
|
||||||
|
clockticks6502++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
saveaccum(result);
|
saveaccum(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +572,6 @@ static void ror() {
|
|||||||
|
|
||||||
if (value & 1) setcarry();
|
if (value & 1) setcarry();
|
||||||
else clearcarry();
|
else clearcarry();
|
||||||
|
|
||||||
zerocalc(result);
|
zerocalc(result);
|
||||||
signcalc(result);
|
signcalc(result);
|
||||||
|
|
||||||
@ -583,6 +599,23 @@ static void sbc() {
|
|||||||
overflowcalc(result, a, value);
|
overflowcalc(result, a, value);
|
||||||
signcalc(result);
|
signcalc(result);
|
||||||
|
|
||||||
|
#ifndef NES_CPU
|
||||||
|
if (status & FLAG_DECIMAL) {
|
||||||
|
clearcarry();
|
||||||
|
|
||||||
|
a -= 0x66;
|
||||||
|
if ((a & 0x0F) > 0x09) {
|
||||||
|
a += 0x06;
|
||||||
|
}
|
||||||
|
if ((a & 0xF0) > 0x90) {
|
||||||
|
a += 0x60;
|
||||||
|
setcarry();
|
||||||
|
}
|
||||||
|
|
||||||
|
clockticks6502++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
saveaccum(result);
|
saveaccum(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,6 +682,67 @@ static void tya() {
|
|||||||
signcalc(a);
|
signcalc(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//undocumented instructions
|
||||||
|
#ifdef UNDOCUMENTED
|
||||||
|
static void lax() {
|
||||||
|
lda();
|
||||||
|
ldx();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sax() {
|
||||||
|
sta();
|
||||||
|
stx();
|
||||||
|
putvalue(a & x);
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcp() {
|
||||||
|
dec();
|
||||||
|
cmp();
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void isb() {
|
||||||
|
inc();
|
||||||
|
sbc();
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void slo() {
|
||||||
|
asl();
|
||||||
|
ora();
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rla() {
|
||||||
|
rol();
|
||||||
|
and();
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sre() {
|
||||||
|
lsr();
|
||||||
|
eor();
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rra() {
|
||||||
|
ror();
|
||||||
|
adc();
|
||||||
|
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define lax nop
|
||||||
|
#define sax nop
|
||||||
|
#define dcp nop
|
||||||
|
#define isb nop
|
||||||
|
#define slo nop
|
||||||
|
#define rla nop
|
||||||
|
#define sre nop
|
||||||
|
#define rra nop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void (*addrtable[256])() = {
|
static void (*addrtable[256])() = {
|
||||||
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
||||||
/* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 0 */
|
/* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 0 */
|
||||||
@ -671,22 +765,22 @@ static void (*addrtable[256])() = {
|
|||||||
|
|
||||||
static void (*optable[256])() = {
|
static void (*optable[256])() = {
|
||||||
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
||||||
/* 0 */ brk, ora, nop, nop, nop, ora, asl, nop, php, ora, asl, nop, nop, ora, asl, nop, /* 0 */
|
/* 0 */ brk, ora, nop, slo, nop, ora, asl, slo, php, ora, asl, nop, nop, ora, asl, slo, /* 0 */
|
||||||
/* 1 */ bpl, ora, nop, nop, nop, ora, asl, nop, clc, ora, nop, nop, nop, ora, asl, nop, /* 1 */
|
/* 1 */ bpl, ora, nop, slo, nop, ora, asl, slo, clc, ora, nop, slo, nop, ora, asl, slo, /* 1 */
|
||||||
/* 2 */ jsr, and, nop, nop, bit, and, rol, nop, plp, and, rol, nop, bit, and, rol, nop, /* 2 */
|
/* 2 */ jsr, and, nop, rla, bit, and, rol, rla, plp, and, rol, nop, bit, and, rol, rla, /* 2 */
|
||||||
/* 3 */ bmi, and, nop, nop, nop, and, rol, nop, sec, and, nop, nop, nop, and, rol, nop, /* 3 */
|
/* 3 */ bmi, and, nop, rla, nop, and, rol, rla, sec, and, nop, rla, nop, and, rol, rla, /* 3 */
|
||||||
/* 4 */ rti, eor, nop, nop, nop, eor, lsr, nop, pha, eor, lsr, nop, jmp, eor, lsr, nop, /* 4 */
|
/* 4 */ rti, eor, nop, sre, nop, eor, lsr, sre, pha, eor, lsr, nop, jmp, eor, lsr, sre, /* 4 */
|
||||||
/* 5 */ bvc, eor, nop, nop, nop, eor, lsr, nop, cli, eor, nop, nop, nop, eor, lsr, nop, /* 5 */
|
/* 5 */ bvc, eor, nop, sre, nop, eor, lsr, sre, cli, eor, nop, sre, nop, eor, lsr, sre, /* 5 */
|
||||||
/* 6 */ rts, adc, nop, nop, nop, adc, ror, nop, pla, adc, ror, nop, jmp, adc, ror, nop, /* 6 */
|
/* 6 */ rts, adc, nop, rra, nop, adc, ror, rra, pla, adc, ror, nop, jmp, adc, ror, rra, /* 6 */
|
||||||
/* 7 */ bvs, adc, nop, nop, nop, adc, ror, nop, sei, adc, nop, nop, nop, adc, ror, nop, /* 7 */
|
/* 7 */ bvs, adc, nop, rra, nop, adc, ror, rra, sei, adc, nop, rra, nop, adc, ror, rra, /* 7 */
|
||||||
/* 8 */ nop, sta, nop, nop, sty, sta, stx, nop, dey, nop, txa, nop, sty, sta, stx, nop, /* 8 */
|
/* 8 */ nop, sta, nop, sax, sty, sta, stx, sax, dey, nop, txa, nop, sty, sta, stx, sax, /* 8 */
|
||||||
/* 9 */ bcc, sta, nop, nop, sty, sta, stx, nop, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */
|
/* 9 */ bcc, sta, nop, nop, sty, sta, stx, sax, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */
|
||||||
/* A */ ldy, lda, ldx, nop, ldy, lda, ldx, nop, tay, lda, tax, nop, ldy, lda, ldx, nop, /* A */
|
/* A */ ldy, lda, ldx, lax, ldy, lda, ldx, lax, tay, lda, tax, nop, ldy, lda, ldx, lax, /* A */
|
||||||
/* B */ bcs, lda, nop, nop, ldy, lda, ldx, nop, clv, lda, tsx, nop, ldy, lda, ldx, nop, /* B */
|
/* B */ bcs, lda, nop, lax, ldy, lda, ldx, lax, clv, lda, tsx, lax, ldy, lda, ldx, lax, /* B */
|
||||||
/* C */ cpy, cmp, nop, nop, cpy, cmp, dec, nop, iny, cmp, dex, nop, cpy, cmp, dec, nop, /* C */
|
/* C */ cpy, cmp, nop, dcp, cpy, cmp, dec, dcp, iny, cmp, dex, nop, cpy, cmp, dec, dcp, /* C */
|
||||||
/* D */ bne, cmp, nop, nop, nop, cmp, dec, nop, cld, cmp, nop, nop, nop, cmp, dec, nop, /* D */
|
/* D */ bne, cmp, nop, dcp, nop, cmp, dec, dcp, cld, cmp, nop, dcp, nop, cmp, dec, dcp, /* D */
|
||||||
/* E */ cpx, sbc, nop, nop, cpx, sbc, inc, nop, inx, sbc, nop, sbc, cpx, sbc, inc, nop, /* E */
|
/* E */ cpx, sbc, nop, isb, cpx, sbc, inc, isb, inx, sbc, nop, sbc, cpx, sbc, inc, isb, /* E */
|
||||||
/* F */ beq, sbc, nop, nop, nop, sbc, inc, nop, sed, sbc, nop, nop, nop, sbc, inc, nop /* F */
|
/* F */ beq, sbc, nop, isb, nop, sbc, inc, isb, sed, sbc, nop, isb, nop, sbc, inc, isb /* F */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t ticktable[256] = {
|
static const uint32_t ticktable[256] = {
|
||||||
@ -741,6 +835,8 @@ void exec6502(uint32_t tickcount) {
|
|||||||
clockticks6502 += ticktable[opcode];
|
clockticks6502 += ticktable[opcode];
|
||||||
if (penaltyop && penaltyaddr) clockticks6502++;
|
if (penaltyop && penaltyaddr) clockticks6502++;
|
||||||
|
|
||||||
|
instructions++;
|
||||||
|
|
||||||
if (callexternal) (*loopexternal)();
|
if (callexternal) (*loopexternal)();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,6 +854,8 @@ void step6502() {
|
|||||||
if (penaltyop && penaltyaddr) clockticks6502++;
|
if (penaltyop && penaltyaddr) clockticks6502++;
|
||||||
clockgoal6502 = clockticks6502;
|
clockgoal6502 = clockticks6502;
|
||||||
|
|
||||||
|
instructions++;
|
||||||
|
|
||||||
if (callexternal) (*loopexternal)();
|
if (callexternal) (*loopexternal)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
117
src/video.c
117
src/video.c
@ -1,117 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <SFML/System.h>
|
|
||||||
#include <SFML/Graphics.h>
|
|
||||||
#include <SFML/Window.h>
|
|
||||||
|
|
||||||
/* Public Variables */
|
|
||||||
extern sfVertexArray *renderArray;
|
|
||||||
int8_t videoModified;
|
|
||||||
int8_t videoMode;
|
|
||||||
|
|
||||||
/* Private Variables */
|
|
||||||
static uint8_t video_row;
|
|
||||||
static uint8_t video_value;
|
|
||||||
static uint8_t video_colorValue;
|
|
||||||
static sfColor video_displayColor;
|
|
||||||
static sfColor video_foreColor;
|
|
||||||
static sfColor video_backColor;
|
|
||||||
|
|
||||||
const sfColor video_upperPalette = (sfColor){ 64, 64, 64 };
|
|
||||||
|
|
||||||
static sfColor *video_colorIndex[16] = {
|
|
||||||
&sfBlack, // 0x0
|
|
||||||
&sfRed, // 0x1
|
|
||||||
&sfGreen, // 0x2
|
|
||||||
&sfYellow, // 0x3
|
|
||||||
&sfBlue, // 0x4
|
|
||||||
&sfMagenta, // 0x5
|
|
||||||
&sfCyan, // 0x6
|
|
||||||
&(sfColor){ 96, 96, 96 }, // 0x7
|
|
||||||
|
|
||||||
&(sfColor){ 162, 162, 162 },// 0x8
|
|
||||||
&sfRed, // 0x9
|
|
||||||
&sfGreen, // 0xA
|
|
||||||
&sfYellow, // 0xB
|
|
||||||
&sfBlue, // 0xC
|
|
||||||
&sfMagenta, // 0xD
|
|
||||||
&sfCyan, // 0xE
|
|
||||||
&sfWhite, // 0xF
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t video_memory[0x8000]; // Empty Memory with 32k space
|
|
||||||
|
|
||||||
void initVideo(){
|
|
||||||
renderArray = sfVertexArray_create();
|
|
||||||
sfVertexArray_setPrimitiveType(renderArray, sfQuads);
|
|
||||||
|
|
||||||
videoModified = 1;
|
|
||||||
videoMode = 0;
|
|
||||||
|
|
||||||
for (int i = 0x8; i < 0xF; i++){
|
|
||||||
//*video_colorIndex[i] = sfColor_add(*video_colorIndex[i], video_upperPalette);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 0x8000; i++){
|
|
||||||
video_memory[i] = rand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateVideo(){
|
|
||||||
sfVertexArray_clear(renderArray);
|
|
||||||
sfVertexArray_setPrimitiveType(renderArray, sfQuads);
|
|
||||||
|
|
||||||
videoModified = 0;
|
|
||||||
|
|
||||||
for (int y = 0; y < 256; y++){
|
|
||||||
video_row = (int8_t)(y & 0x7);
|
|
||||||
|
|
||||||
for (int x = 0; x < 48; x++){
|
|
||||||
|
|
||||||
if (videoMode == 1){
|
|
||||||
/*
|
|
||||||
* Text Address Format
|
|
||||||
* 0bRRR1111AAAAAAAA
|
|
||||||
*
|
|
||||||
* R = row pins
|
|
||||||
* A = address
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Get text index value
|
|
||||||
video_value = video_memory[(((y & 0xF8) >> 3) << 7) | x];
|
|
||||||
|
|
||||||
// Index the value in font location
|
|
||||||
video_value = video_memory[(video_row | 0b1111000) + (video_value * 128)];
|
|
||||||
video_colorValue = video_memory[(((y & 0xF8) >> 3) << 7) + (x | 0x40)];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
video_value = video_memory[(y * 128) + x];
|
|
||||||
video_colorValue = video_memory[(y * 128) + (x | 0x40)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snipping out the upper 8 colors
|
|
||||||
//video_colorValue &= 0x77;
|
|
||||||
|
|
||||||
video_foreColor = *video_colorIndex[(video_colorValue & 0x0F)];
|
|
||||||
video_backColor = *video_colorIndex[((video_colorValue & 0xF0) >> 4)];
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (video_value & (128 >> i)){
|
|
||||||
video_displayColor = video_foreColor;
|
|
||||||
} else {
|
|
||||||
video_displayColor = video_backColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i, y }, video_displayColor});
|
|
||||||
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i + 1, y }, video_displayColor});
|
|
||||||
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i + 1, y + 1 }, video_displayColor});
|
|
||||||
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i, y + 1 }, video_displayColor});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user