Compare commits
7 Commits
04f0fe2c7b
...
45b8993cdd
Author | SHA1 | Date | |
---|---|---|---|
![]() |
45b8993cdd | ||
![]() |
5cc21f3a6f | ||
![]() |
caba72b134 | ||
![]() |
3a7dc09389 | ||
![]() |
c824ad0989 | ||
![]() |
de0686edb7 | ||
![]() |
8581e53373 |
14
Makefile
14
Makefile
@ -1,9 +1,10 @@
|
|||||||
.ONESHELL:
|
.ONESHELL:
|
||||||
|
|
||||||
CC=gcc
|
CC = gcc
|
||||||
O=2
|
O = 3
|
||||||
CFLAGS=`sdl2-config --cflags` `sdl2-config --libs`
|
CFLAGS = `sdl2-config --cflags` `sdl2-config --libs`
|
||||||
PREFIX=$(HOME)/.local
|
PREFIX = $(HOME)/.local
|
||||||
|
SRC = main.c
|
||||||
|
|
||||||
all: ls7emulator
|
all: ls7emulator
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ clean:
|
|||||||
|
|
||||||
ls7emulator:
|
ls7emulator:
|
||||||
cd src
|
cd src
|
||||||
$(CC) main.c -o ls7emulator $(CFLAGS) -O$(O)
|
$(CC) $(SRC) -o ls7emulator $(CFLAGS) -O$(O)
|
||||||
rm ../bin -rf
|
rm ../bin -rf
|
||||||
mkdir ../bin
|
mkdir ../bin
|
||||||
cd ../bin
|
cd ../bin
|
||||||
@ -24,3 +25,6 @@ install: ls7emulator
|
|||||||
mkdir -p $(PREFIX)/bin
|
mkdir -p $(PREFIX)/bin
|
||||||
install bin/ls7emulator $(PREFIX)/bin/ls7emulator
|
install bin/ls7emulator $(PREFIX)/bin/ls7emulator
|
||||||
cp bin/ls7emulator /usr/bin/ls7emulator
|
cp bin/ls7emulator /usr/bin/ls7emulator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
20
src/config.h
20
src/config.h
@ -10,24 +10,28 @@
|
|||||||
#define ROMLOC 0xC000 /* ROM Page Location */
|
#define ROMLOC 0xC000 /* ROM Page Location */
|
||||||
|
|
||||||
#define BACKCOLOR sfBlack
|
#define BACKCOLOR sfBlack
|
||||||
#define SCREEN_WIDTH 768
|
#define SDL_X_SIZE 384
|
||||||
#define SCREEN_HEIGHT 512
|
#define SDL_Y_SIZE 256
|
||||||
#define SDL_X_SIZE 768
|
|
||||||
#define SDL_Y_SIZE 512
|
|
||||||
|
|
||||||
#define PREAMBLE "LS7 Emulator by Gabriel Weingardt.\nLicense: GPL v.3+\n\n"
|
#define PREAMBLE "LS7 Emulator by Gabriel Weingardt.\n\
|
||||||
|
License: GPL v.3+\n\
|
||||||
|
See: https://git.weingardt.dev/0xmac/LS7-Emulator\n\n"
|
||||||
|
|
||||||
#define HELP "Usage: LS7Emulator [options] ... [file]\n\n\
|
#define HELP "Usage: LS7Emulator [options] ... [file]\n\n\
|
||||||
Options: Type Default Desc\n\
|
Options: Type Default Desc\n\
|
||||||
--help Show this menu\n\
|
--help Show this menu\n\
|
||||||
--help-keys Show emulator key functions\n\
|
--help-keys Show emulator key functions\n\
|
||||||
--cpuspeed [int] 100000 CPU Speed given in Herz. KHz and MHz annotations like 1KHz are supported\n\
|
--resizeable Make the window resizable\n\
|
||||||
--scale [float] 2.0 Set the starting scale of the video output\n\
|
|
||||||
--singlestep Enable singlestepping with the 'F8' key\n\
|
--singlestep Enable singlestepping with the 'F8' key\n\
|
||||||
|
--reload-program Reload the binary file when CPU is reset\n\
|
||||||
|
--randomize Randomize Computer and video RAM on reset\n\
|
||||||
|
\n\
|
||||||
|
--cpuspeed [int] 1MHz CPU Speed given in Herz. KHz and MHz formats like 1KHz are supported\n\
|
||||||
|
--scale [float] 1 Set the starting scale of the video output\n\
|
||||||
--clocksteps [int] 1 Set the clock cycles cycled by a singlestep\n\
|
--clocksteps [int] 1 Set the clock cycles cycled by a singlestep\n\
|
||||||
--snapshot [string] Import a CPU snapshot\n\
|
--snapshot [string] Import a CPU snapshot\n\
|
||||||
--fps [float] 30 Set the SDL FPS rate\n\
|
--fps [float] 30 Set the SDL FPS rate\n\
|
||||||
--enable-reload Reload the binary file when CPU is reset\n\
|
--script [string] Execute a script when CPU is being reset (helpful for development)\n\
|
||||||
\n"
|
\n"
|
||||||
|
|
||||||
#define HELPKEYS "\
|
#define HELPKEYS "\
|
||||||
|
203
src/cpu.c
203
src/cpu.c
@ -1,7 +1,7 @@
|
|||||||
/* Fake6502 CPU emulator core v1.1 *******************
|
/* Fake6502 CPU emulator core v1.1 *******************
|
||||||
* (c)2011-2013 Mike Chambers *
|
* (c)2011-2013 Mike Chambers *
|
||||||
* *
|
* *
|
||||||
* Modified by Gabriel Weingardt *
|
* Modified for 65c02 by Gabriel Weingardt *
|
||||||
*****************************************************/
|
*****************************************************/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -130,6 +130,10 @@ static void zp() { //zero-page
|
|||||||
ea = (uint16_t)read6502((uint16_t)pc++);
|
ea = (uint16_t)read6502((uint16_t)pc++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void izp() { // zero-page indirect (new 65c02 instruction)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void zpx() { //zero-page,X
|
static void zpx() { //zero-page,X
|
||||||
ea = ((uint16_t)read6502((uint16_t)pc++) + (uint16_t)x) & 0xFF; //zero-page wraparound
|
ea = ((uint16_t)read6502((uint16_t)pc++) + (uint16_t)x) & 0xFF; //zero-page wraparound
|
||||||
}
|
}
|
||||||
@ -201,6 +205,16 @@ static void indy() { // (indirect),Y
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// new 65c02 address mode
|
||||||
|
static void aii() { // absolute indexed indirect
|
||||||
|
uint16_t eahelp, eahelp2;
|
||||||
|
eahelp = ((uint16_t)read6502(pc) | ((uint16_t)read6502(pc+1) << 8)) + x;
|
||||||
|
eahelp2 = (eahelp & 0xFF00) | ((eahelp + 1) & 0x00FF); //replicate 6502 page-boundary wraparound bug
|
||||||
|
ea = (uint16_t)read6502(eahelp) | ((uint16_t)read6502(eahelp2) << 8);
|
||||||
|
pc += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint16_t getvalue() {
|
static uint16_t getvalue() {
|
||||||
if (addrtable[opcode] == acc) return((uint16_t)a);
|
if (addrtable[opcode] == acc) return((uint16_t)a);
|
||||||
else return((uint16_t)read6502(ea));
|
else return((uint16_t)read6502(ea));
|
||||||
@ -336,6 +350,37 @@ static void bvs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bra() { // new 65c02 instruction
|
||||||
|
oldpc = pc;
|
||||||
|
pc += reladdr;
|
||||||
|
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||||
|
else clockticks6502++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bbr() { // new 65c02 instruction
|
||||||
|
uint8_t testval = 1;
|
||||||
|
for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1;
|
||||||
|
|
||||||
|
if (!(a & testval)) {
|
||||||
|
oldpc = pc;
|
||||||
|
pc += reladdr;
|
||||||
|
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||||
|
else clockticks6502++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bbs() { // new 65c02 instruction
|
||||||
|
uint8_t testval = 1;
|
||||||
|
for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1;
|
||||||
|
|
||||||
|
if (a & testval) {
|
||||||
|
oldpc = pc;
|
||||||
|
pc += reladdr;
|
||||||
|
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||||
|
else clockticks6502++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void clc() {
|
static void clc() {
|
||||||
clearcarry();
|
clearcarry();
|
||||||
}
|
}
|
||||||
@ -522,9 +567,18 @@ static void pha() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void php() {
|
static void php() {
|
||||||
push8(status | FLAG_BREAK);
|
push8(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void phy() { // new 65c02 instruction
|
||||||
|
push8(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void phx() { // new 65c02 instruction
|
||||||
|
push8(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pla() {
|
static void pla() {
|
||||||
a = pull8();
|
a = pull8();
|
||||||
|
|
||||||
@ -536,6 +590,21 @@ static void plp() {
|
|||||||
status = pull8() | FLAG_CONSTANT;
|
status = pull8() | FLAG_CONSTANT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ply() { // new 65c02 instruction
|
||||||
|
y = pull8();
|
||||||
|
|
||||||
|
zerocalc(y);
|
||||||
|
signcalc(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plx() { // new 65c02 instruction
|
||||||
|
a = pull8();
|
||||||
|
|
||||||
|
zerocalc(x);
|
||||||
|
signcalc(x);
|
||||||
|
}
|
||||||
|
|
||||||
static void rol() {
|
static void rol() {
|
||||||
value = getvalue();
|
value = getvalue();
|
||||||
result = (value << 1) | (status & FLAG_CARRY);
|
result = (value << 1) | (status & FLAG_CARRY);
|
||||||
@ -608,6 +677,10 @@ static void sty() {
|
|||||||
putvalue(y);
|
putvalue(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stz() { // new 65c02 instruction
|
||||||
|
putvalue(0);
|
||||||
|
}
|
||||||
|
|
||||||
static void tax() {
|
static void tax() {
|
||||||
x = a;
|
x = a;
|
||||||
|
|
||||||
@ -647,44 +720,88 @@ static void tya() {
|
|||||||
signcalc(a);
|
signcalc(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void (*addrtable[256])() = {
|
static void trb() { // new 65c02 instruction
|
||||||
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
value = getvalue();
|
||||||
/* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 0 */
|
result = value & ~a;
|
||||||
/* 1 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 1 */
|
|
||||||
/* 2 */ abso, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 2 */
|
zerocalc(result);
|
||||||
/* 3 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 3 */
|
putvalue(result);
|
||||||
/* 4 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 4 */
|
}
|
||||||
/* 5 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 5 */
|
|
||||||
/* 6 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, ind, abso, abso, abso, /* 6 */
|
static void tsb() { // new 65c02 instruction
|
||||||
/* 7 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 7 */
|
value = getvalue();
|
||||||
/* 8 */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* 8 */
|
result = value | a;
|
||||||
/* 9 */ rel, indy, imp, indy, zpx, zpx, zpy, zpy, imp, absy, imp, absy, absx, absx, absy, absy, /* 9 */
|
|
||||||
/* A */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* A */
|
zerocalc(result);
|
||||||
/* B */ rel, indy, imp, indy, zpx, zpx, zpy, zpy, imp, absy, imp, absy, absx, absx, absy, absy, /* B */
|
putvalue(result);
|
||||||
/* C */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* C */
|
}
|
||||||
/* D */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* D */
|
|
||||||
/* E */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* E */
|
static void rmb() { // new 65c02 instruction
|
||||||
/* F */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx /* F */
|
uint8_t testval = 1;
|
||||||
};
|
for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1;
|
||||||
|
|
||||||
|
value = getvalue();
|
||||||
|
result = value & ~testval;
|
||||||
|
|
||||||
|
putvalue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smb() { // new 65c02 instruction
|
||||||
|
uint8_t testval = 1;
|
||||||
|
for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1;
|
||||||
|
|
||||||
|
value = getvalue();
|
||||||
|
result = value | testval;
|
||||||
|
|
||||||
|
putvalue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wai() { // new 65c02 instruction
|
||||||
|
// implement later
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stp() { // new 65c02 instruction
|
||||||
|
// implement later
|
||||||
|
}
|
||||||
|
|
||||||
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, nop, tsb, ora, asl, rmb, php, ora, asl, nop, tsb, ora, asl, bbr, /* 0 */
|
||||||
/* 1 */ bpl, ora, nop, nop, nop, ora, asl, nop, clc, ora, nop, nop, nop, ora, asl, nop, /* 1 */
|
/* 1 */ bpl, ora, ora, nop, trb, ora, asl, rmb, clc, ora, inc, nop, trb, ora, asl, bbr, /* 1 */
|
||||||
/* 2 */ jsr, and, nop, nop, bit, and, rol, nop, plp, and, rol, nop, bit, and, rol, nop, /* 2 */
|
/* 2 */ jsr, and, nop, nop, bit, and, rol, rmb, plp, and, rol, nop, bit, and, rol, bbr, /* 2 */
|
||||||
/* 3 */ bmi, and, nop, nop, nop, and, rol, nop, sec, and, nop, nop, nop, and, rol, nop, /* 3 */
|
/* 3 */ bmi, and, and, nop, bit, and, rol, rmb, sec, and, dec, nop, bit, and, rol, bbr, /* 3 */
|
||||||
/* 4 */ rti, eor, nop, nop, nop, eor, lsr, nop, pha, eor, lsr, nop, jmp, eor, lsr, nop, /* 4 */
|
/* 4 */ rti, eor, nop, nop, nop, eor, lsr, rmb, pha, eor, lsr, nop, jmp, eor, lsr, bbr, /* 4 */
|
||||||
/* 5 */ bvc, eor, nop, nop, nop, eor, lsr, nop, cli, eor, nop, nop, nop, eor, lsr, nop, /* 5 */
|
/* 5 */ bvc, eor, eor, nop, nop, eor, lsr, rmb, cli, eor, phy, nop, nop, eor, lsr, bbr, /* 5 */
|
||||||
/* 6 */ rts, adc, nop, nop, nop, adc, ror, nop, pla, adc, ror, nop, jmp, adc, ror, nop, /* 6 */
|
/* 6 */ rts, adc, nop, nop, stz, adc, ror, rmb, pla, adc, ror, nop, jmp, adc, ror, bbr, /* 6 */
|
||||||
/* 7 */ bvs, adc, nop, nop, nop, adc, ror, nop, sei, adc, nop, nop, nop, adc, ror, nop, /* 7 */
|
/* 7 */ bvs, adc, adc, nop, stz, adc, ror, rmb, sei, adc, ply, nop, jmp, adc, ror, bbr, /* 7 */
|
||||||
/* 8 */ nop, sta, nop, nop, sty, sta, stx, nop, dey, nop, txa, nop, sty, sta, stx, nop, /* 8 */
|
/* 8 */ bra, sta, nop, nop, sty, sta, stx, smb, dey, bit, txa, nop, sty, sta, stx, bbs, /* 8 */
|
||||||
/* 9 */ bcc, sta, nop, nop, sty, sta, stx, nop, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */
|
/* 9 */ bcc, sta, sta, nop, sty, sta, stx, smb, tya, sta, txs, nop, stz, sta, stz, bbs, /* 9 */
|
||||||
/* A */ ldy, lda, ldx, nop, ldy, lda, ldx, nop, tay, lda, tax, nop, ldy, lda, ldx, nop, /* A */
|
/* A */ ldy, lda, ldx, nop, ldy, lda, ldx, smb, tay, lda, tax, nop, ldy, lda, ldx, bbs, /* A */
|
||||||
/* B */ bcs, lda, nop, nop, ldy, lda, ldx, nop, clv, lda, tsx, nop, ldy, lda, ldx, nop, /* B */
|
/* B */ bcs, lda, lda, nop, ldy, lda, ldx, smb, clv, lda, tsx, nop, ldy, lda, ldx, bbs, /* B */
|
||||||
/* C */ cpy, cmp, nop, nop, cpy, cmp, dec, nop, iny, cmp, dex, nop, cpy, cmp, dec, nop, /* C */
|
/* C */ cpy, cmp, nop, nop, cpy, cmp, dec, smb, iny, cmp, dex, wai, cpy, cmp, dec, bbs, /* C */
|
||||||
/* D */ bne, cmp, nop, nop, nop, cmp, dec, nop, cld, cmp, nop, nop, nop, cmp, dec, nop, /* D */
|
/* D */ bne, cmp, cmp, nop, nop, cmp, dec, smb, cld, cmp, phx, stp, nop, cmp, dec, bbs, /* D */
|
||||||
/* E */ cpx, sbc, nop, nop, cpx, sbc, inc, nop, inx, sbc, nop, sbc, cpx, sbc, inc, nop, /* E */
|
/* E */ cpx, sbc, nop, nop, cpx, sbc, inc, smb, inx, sbc, nop, sbc, cpx, sbc, inc, bbs, /* E */
|
||||||
/* F */ beq, sbc, nop, nop, nop, sbc, inc, nop, sed, sbc, nop, nop, nop, sbc, inc, nop /* F */
|
/* F */ beq, sbc, sbc, nop, nop, sbc, inc, smb, sed, sbc, plx, nop, nop, sbc, inc, bbs /* F */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void (*addrtable[256])() = {
|
||||||
|
/* | 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, rel, /* 0 */
|
||||||
|
/* 1 */ rel, indy, izp, indy, zp, zpx, zpx, zp, imp, absy, acc, absy, abso, absx, absx, rel, /* 1 */
|
||||||
|
/* 2 */ abso, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, rel, /* 2 */
|
||||||
|
/* 3 */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, acc, absy, absx, absx, absx, rel, /* 3 */
|
||||||
|
/* 4 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, rel, /* 4 */
|
||||||
|
/* 5 */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, absy, absx, absx, absx, rel, /* 5 */
|
||||||
|
/* 6 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, ind, abso, abso, rel, /* 6 */
|
||||||
|
/* 7 */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, absy, aii, absx, absx, rel, /* 7 */
|
||||||
|
/* 8 */ rel, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, rel, /* 8 */
|
||||||
|
/* 9 */ rel, indy, izp, indy, zpx, zpx, zpy, zp, imp, absy, imp, absy, abso, absx, absx, rel, /* 9 */
|
||||||
|
/* A */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, rel, /* A */
|
||||||
|
/* B */ rel, indy, izp, indy, zpx, zpx, zpy, zp, imp, absy, imp, absy, absx, absx, absy, rel, /* B */
|
||||||
|
/* C */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imp, abso, abso, abso, rel, /* C */
|
||||||
|
/* D */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, imp, absx, absx, absx, rel, /* D */
|
||||||
|
/* E */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, rel, /* E */
|
||||||
|
/* F */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, absy, absx, absx, absx, rel /* F */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t ticktable[256] = {
|
static const uint32_t ticktable[256] = {
|
||||||
@ -716,10 +833,14 @@ void nmi6502() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void irq6502() {
|
void irq6502() {
|
||||||
push16(pc);
|
// only initiate interrupts when interrupt flag is cleared
|
||||||
push8(status);
|
|
||||||
status |= FLAG_INTERRUPT;
|
if (!(status & FLAG_INTERRUPT)){
|
||||||
pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);
|
push16(pc);
|
||||||
|
push8(status);
|
||||||
|
status |= FLAG_INTERRUPT;
|
||||||
|
pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void step6502() {
|
void step6502() {
|
||||||
|
@ -20,6 +20,7 @@ extern void step6502();
|
|||||||
extern void updateRenderStates();
|
extern void updateRenderStates();
|
||||||
extern void scanKeyboard();
|
extern void scanKeyboard();
|
||||||
extern void clearScreen(uint32_t[], uint32_t);
|
extern void clearScreen(uint32_t[], uint32_t);
|
||||||
|
extern void sdlResize();
|
||||||
|
|
||||||
static SDL_Scancode currentKey = SDL_SCANCODE_UNKNOWN;
|
static SDL_Scancode currentKey = SDL_SCANCODE_UNKNOWN;
|
||||||
static SDL_Event event;
|
static SDL_Event event;
|
||||||
@ -65,11 +66,13 @@ void pollEvents(){
|
|||||||
case SDL_SCANCODE_F6: /* Scale -- */
|
case SDL_SCANCODE_F6: /* Scale -- */
|
||||||
clearScreen(renderMemory, 0x000000FF);
|
clearScreen(renderMemory, 0x000000FF);
|
||||||
if (displayScale > 1) displayScale--;
|
if (displayScale > 1) displayScale--;
|
||||||
break;
|
sdlResize();
|
||||||
|
break;
|
||||||
|
|
||||||
case SDL_SCANCODE_F7: /* Scale ++ */
|
case SDL_SCANCODE_F7: /* Scale ++ */
|
||||||
clearScreen(renderMemory, 0x000000FF);
|
clearScreen(renderMemory, 0x000000FF);
|
||||||
displayScale++;
|
displayScale++;
|
||||||
|
sdlResize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_SCANCODE_F8: /* CPU Singlestep */
|
case SDL_SCANCODE_F8: /* CPU Singlestep */
|
||||||
|
78
src/main.c
78
src/main.c
@ -1,4 +1,6 @@
|
|||||||
#include <SDL2/SDL_render.h>
|
#include <SDL2/SDL_render.h>
|
||||||
|
#include <SDL2/SDL_video.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -9,8 +11,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
/* Preset Values */
|
/* Preset Values */
|
||||||
static float displayScale = 2;
|
static float displayScale = 1;
|
||||||
static int cpuSpeed = 100000; // 100 kHz
|
static int cpuSpeed = 1000000; // 1 MHz
|
||||||
static int singleStep = 0;
|
static int singleStep = 0;
|
||||||
static int clockSteps = 1;
|
static int clockSteps = 1;
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ uint8_t showDebug = 0;
|
|||||||
uint8_t fpsCount = 0;
|
uint8_t fpsCount = 0;
|
||||||
uint8_t displayMmap = 0;
|
uint8_t displayMmap = 0;
|
||||||
uint8_t documentReload = 0;
|
uint8_t documentReload = 0;
|
||||||
|
uint8_t randomize = 0;
|
||||||
|
|
||||||
uint8_t fpsStore = 60;
|
uint8_t fpsStore = 60;
|
||||||
uint8_t FPS = 30;
|
uint8_t FPS = 30;
|
||||||
@ -36,12 +39,11 @@ uint8_t cpuHealth;
|
|||||||
unsigned long cpuTicks = 0;
|
unsigned long cpuTicks = 0;
|
||||||
unsigned long tickTrigger = 0;
|
unsigned long tickTrigger = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char debugString[512];
|
char debugString[512];
|
||||||
char snapshotFile[32];
|
char snapshotFile[32];
|
||||||
char *reloadExecute;
|
char *reloadExecute;
|
||||||
char *inputFile;
|
char *inputFile;
|
||||||
|
char *displaySpeed;
|
||||||
|
|
||||||
int openFile(){
|
int openFile(){
|
||||||
FILE *file = fopen(inputFile, "rb");
|
FILE *file = fopen(inputFile, "rb");
|
||||||
@ -61,25 +63,52 @@ int openFile(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resetSystem(){
|
void resetSystem(){
|
||||||
|
srand((unsigned)time(NULL));
|
||||||
|
|
||||||
|
if (randomize) {
|
||||||
|
for (int i = 0; i < RAMSIZE + 1; i++) ram[i] = rand();
|
||||||
|
}
|
||||||
|
|
||||||
initVideo();
|
initVideo();
|
||||||
updateVideo();
|
updateVideo();
|
||||||
reset6502();
|
reset6502();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetchArgs(int argc, char *argv[]){
|
int parseFormat(char *format){
|
||||||
printf(PREAMBLE);
|
float retVal = 0;
|
||||||
|
int i = 0;
|
||||||
|
for (;isdigit(format[i]) || format[i] == '.'; i++);
|
||||||
|
|
||||||
|
char tmp = format[i];
|
||||||
|
format[i] = 0;
|
||||||
|
retVal = atof(format);
|
||||||
|
format[i] = tmp;
|
||||||
|
|
||||||
|
if (!strcasecmp((format + i), "hz"));
|
||||||
|
else if (!strcasecmp((format + i), "khz")) retVal *= 1000;
|
||||||
|
else if (!strcasecmp((format + i), "mhz")) retVal *= 1000000;
|
||||||
|
else {
|
||||||
|
printf("\"%s\" is not a supported format\nSupported formats include: Hz, KHz and MHz\n", (format + i));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetchArgs(int argc, char *argv[]){
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (!strcmp(argv[i], "--help")) printf(HELP);
|
if (!strcmp(argv[i], "--help")) { printf(PREAMBLE); printf(HELP); exit(0); }
|
||||||
else if (!strcmp(argv[i], "--help-keys")) printf(HELPKEYS);
|
else if (!strcmp(argv[i], "--help-keys")) { printf(PREAMBLE); printf(HELPKEYS); exit(0); }
|
||||||
else if (!strcmp(argv[i], "--cpuspeed")) cpuSpeed = atoi(argv[++i]);
|
else if (!strcmp(argv[i], "--cpuspeed")) { cpuSpeed = parseFormat(argv[++i]); displaySpeed = argv[i]; }
|
||||||
else if (!strcmp(argv[i], "--scale")) displayScale = atof(argv[++i]);
|
else if (!strcmp(argv[i], "--scale")) displayScale = atof(argv[++i]);
|
||||||
else if (!strcmp(argv[i], "--singlestep")) singleStep = 1;
|
else if (!strcmp(argv[i], "--singlestep")) singleStep = 1;
|
||||||
else if (!strcmp(argv[i], "--clocksteps")) clockSteps = atoi(argv[++i]);
|
else if (!strcmp(argv[i], "--clocksteps")) clockSteps = atoi(argv[++i]);
|
||||||
//else if (!strcmp(argv[i], "--snapshot")) snapshotFile = &argv[i];
|
//else if (!strcmp(argv[i], "--snapshot")) snapshotFile = &argv[i];
|
||||||
else if (!strcmp(argv[i], "--fps")) FPS = atoi(argv[++i]);
|
else if (!strcmp(argv[i], "--fps")) FPS = atoi(argv[++i]);
|
||||||
else if (!strcmp(argv[i], "--enable-reload")) documentReload = 1;
|
else if (!strcmp(argv[i], "--reload-program")) documentReload = 1;
|
||||||
else if (!strcmp(argv[i], "--reload-execute")) reloadExecute = argv[++i];
|
else if (!strcmp(argv[i], "--script")) reloadExecute = argv[++i];
|
||||||
|
else if (!strcmp(argv[i], "--resizable")) WINMODE |= SDL_WINDOW_RESIZABLE;
|
||||||
|
else if (!strcmp(argv[i], "--randomize")) randomize = 1;
|
||||||
else {
|
else {
|
||||||
inputFile = argv[i];
|
inputFile = argv[i];
|
||||||
if (openFile()){
|
if (openFile()){
|
||||||
@ -90,6 +119,7 @@ void fetchArgs(int argc, char *argv[]){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]){
|
int main(int argc, char *argv[]){
|
||||||
fetchArgs(argc, argv);
|
fetchArgs(argc, argv);
|
||||||
initWindow();
|
initWindow();
|
||||||
@ -129,35 +159,33 @@ int main(int argc, char *argv[]){
|
|||||||
|
|
||||||
if (halt) {
|
if (halt) {
|
||||||
drawString("!CPU Haltet!", renderMemory,
|
drawString("!CPU Haltet!", renderMemory,
|
||||||
SDL_X_SIZE, 0x000000FF, time(NULL) % 2 ? 0xAAAAAAFF : 0xFFFFFFFF, 16, vStack, 2);
|
SDL_X_SIZE, 0x000000FF, time(NULL) % 2 ? 0xAAAAAAFF : 0xFFFFFFFF, 16, vStack, 1);
|
||||||
|
|
||||||
vStack += (FONT_HEIGHT * 2 * 2);
|
vStack += (FONT_HEIGHT * 2);
|
||||||
} if (showDebug){
|
} if (showDebug){
|
||||||
sprintf(debugString, "LOADED BINARY: \"%s\"\nSCREENSIZE: %dx%d\nFPS: %d\nSCALE: %d", inputFile, SDL_X_SIZE, SDL_Y_SIZE, fpsStore, (int)displayScale);
|
sprintf(debugString, "LOADED BINARY: \"%s\"\nSCREENSIZE: %dx%d\nFPS: %d\nSCALE: %d", inputFile, SDL_X_SIZE, SDL_Y_SIZE, fpsStore, (int)displayScale);
|
||||||
drawString(debugString, renderMemory,
|
drawString(debugString, renderMemory,
|
||||||
SDL_X_SIZE, 0x000000FF, 0xAAAAAAFF, 16, vStack, 2);
|
SDL_X_SIZE, 0x000000FF, 0xAAAAAAFF, 16, vStack, 1);
|
||||||
|
|
||||||
vStack += (FONT_HEIGHT * 4 * 2);
|
vStack += (FONT_HEIGHT * 4);
|
||||||
|
|
||||||
sprintf(debugString, "CPU: %d%%", cpuHealth);
|
sprintf(debugString, "CPU: %d%% @ %s", cpuHealth, displaySpeed);
|
||||||
drawString(debugString, renderMemory,
|
drawString(debugString, renderMemory,
|
||||||
SDL_X_SIZE, 0x000000FF, time(NULL) % 2 ? 0xAAAAAAFF : cpuHealth < 10 ?
|
SDL_X_SIZE, 0x000000FF, time(NULL) % 2 ? 0xAAAAAAFF : cpuHealth < 10 ?
|
||||||
0xFF0000FF : cpuHealth < 50 ? 0xFFFF00FF : 0xAAAAAAFF, 16, vStack, 2);
|
0xFF0000FF : cpuHealth < 50 ? 0xFFFF00FF : 0xAAAAAAFF, 16, vStack, 1);
|
||||||
|
|
||||||
vStack += (FONT_HEIGHT * 2 * 2);
|
vStack += (FONT_HEIGHT * 2);
|
||||||
} if (displayMmap){
|
} if (displayMmap){
|
||||||
sprintf(debugString, "RAM: $%04X - $%04X\nROM: $%04X - $%04X\nVIAADDRS: $%04X\nKBDADDRS: $%04X\nVIDADDRS: $%04X", RAMLOC, RAMLOC + RAMSIZE, ROMLOC, ROMLOC + ROMSIZE, VIAADDRS, KBDADDRS, VIDADDRS);
|
sprintf(debugString, "RAM: $%04X - $%04X\nROM: $%04X - $%04X\nVIAADDRS: $%04X\nKBDADDRS: $%04X\nVIDADDRS: $%04X", RAMLOC, RAMLOC + RAMSIZE, ROMLOC, ROMLOC + ROMSIZE, VIAADDRS, KBDADDRS, VIDADDRS);
|
||||||
drawString(debugString, renderMemory, SDL_X_SIZE, 0x000000FF, 0xAAAAAAFF, 16, vStack, 2);
|
drawString(debugString, renderMemory, SDL_X_SIZE, 0x000000FF, 0xAAAAAAFF, 16, vStack, 1);
|
||||||
|
|
||||||
vStack += (FONT_HEIGHT * 6 * 2);
|
vStack += (FONT_HEIGHT * 6);
|
||||||
} if (showHelp) {
|
} if (showHelp) {
|
||||||
drawString(HELPKEYS, renderMemory, SDL_X_SIZE, 0x000000FF, 0xAAAAAAFF, 16, vStack, 2);
|
drawString(HELPKEYS, renderMemory, SDL_X_SIZE, 0x000000FF, 0xAAAAAAFF, 16, vStack, 1);
|
||||||
|
|
||||||
vStack += (FONT_HEIGHT * 2 * 2);
|
vStack += (FONT_HEIGHT * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (SDL_UpdateTexture(texture, NULL, renderMemory, (sizeof(uint32_t) * SDL_X_SIZE))) {
|
if (SDL_UpdateTexture(texture, NULL, renderMemory, (sizeof(uint32_t) * SDL_X_SIZE))) {
|
||||||
fprintf(stderr, "Could not update SDL texture: %s.\n", SDL_GetError());
|
fprintf(stderr, "Could not update SDL texture: %s.\n", SDL_GetError());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_video.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
|
||||||
|
extern float displayScale;
|
||||||
|
int WINMODE = 0;
|
||||||
|
|
||||||
static SDL_Window *window;
|
static SDL_Window *window;
|
||||||
static SDL_Renderer *renderer;
|
static SDL_Renderer *renderer;
|
||||||
static SDL_Texture *texture;
|
static SDL_Texture *texture;
|
||||||
@ -16,7 +20,7 @@ void initWindow(){
|
|||||||
|
|
||||||
window = SDL_CreateWindow("LS7 Emulator",
|
window = SDL_CreateWindow("LS7 Emulator",
|
||||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||||
SCREEN_WIDTH, SCREEN_HEIGHT, 0);
|
SDL_X_SIZE, SDL_Y_SIZE, WINMODE);
|
||||||
if (window == NULL){
|
if (window == NULL){
|
||||||
printf("Fatal! Could not create SDL Window: %s\n", SDL_GetError());
|
printf("Fatal! Could not create SDL Window: %s\n", SDL_GetError());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -30,7 +34,7 @@ void initWindow(){
|
|||||||
|
|
||||||
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
SCREEN_WIDTH, SCREEN_HEIGHT);
|
SDL_X_SIZE, SDL_Y_SIZE);
|
||||||
if (texture == NULL){
|
if (texture == NULL){
|
||||||
printf("Fatal! Could not create SDL Texture: %s\n", SDL_GetError());
|
printf("Fatal! Could not create SDL Texture: %s\n", SDL_GetError());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -42,6 +46,10 @@ void initWindow(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sdlResize(){
|
||||||
|
SDL_SetWindowSize(window, SDL_X_SIZE * displayScale, SDL_Y_SIZE * displayScale);
|
||||||
|
}
|
||||||
|
|
||||||
void clearScreen(uint32_t pixels[], uint32_t color){
|
void clearScreen(uint32_t pixels[], uint32_t color){
|
||||||
for (uint32_t i = 0; i < SDL_X_SIZE * SDL_Y_SIZE; i++) pixels[i] = color;
|
for (uint32_t i = 0; i < SDL_X_SIZE * SDL_Y_SIZE; i++) pixels[i] = color;
|
||||||
}
|
}
|
||||||
|
24
src/video.c
24
src/video.c
@ -6,6 +6,7 @@
|
|||||||
#define LOWCOLOR 96
|
#define LOWCOLOR 96
|
||||||
|
|
||||||
extern float displayScale;
|
extern float displayScale;
|
||||||
|
extern uint8_t randomize;
|
||||||
|
|
||||||
/* Public Variables */
|
/* Public Variables */
|
||||||
int8_t videoModified;
|
int8_t videoModified;
|
||||||
@ -50,8 +51,9 @@ void initVideo(){
|
|||||||
videoMode = 0x01;
|
videoMode = 0x01;
|
||||||
updatePalette();
|
updatePalette();
|
||||||
|
|
||||||
/* Fill VRAM with random values, just for fun */
|
if (randomize) {
|
||||||
for (int i = 0; i < 0x8000; i++) videoMemory[i] = rand();
|
for (int i = 0; i < 0x8000; i++) videoMemory[i] = rand();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeVideo(){
|
void writeVideo(){
|
||||||
@ -86,26 +88,16 @@ void setPixels(uint8_t x, uint8_t y){
|
|||||||
videoColorValue = videoMemory[(y * 128) + (x | 0x40)];
|
videoColorValue = videoMemory[(y * 128) + (x | 0x40)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snipping out the upper 8 colors
|
|
||||||
// videoColorValue &= 0x77;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 8; i++){
|
for (uint8_t i = 0; i < 8; i++){
|
||||||
if (displayScale == 1){
|
renderMemory[(y * SDL_X_SIZE) + ((x * 8) + i)] =
|
||||||
renderMemory[(y * SDL_X_SIZE) + ((x * 8) + i)] = (videoValue & (128 >> i)) ? videoColorIndex[((videoColorValue & 0xF0) >> 4)] : videoColorIndex[(videoColorValue & 0x0F)];
|
(videoValue & (128 >> i)) ?
|
||||||
} else {
|
videoColorIndex[((videoColorValue & 0xF0) >> 4)] :
|
||||||
for (uint8_t _x = 0; _x < displayScale; _x++){
|
videoColorIndex[(videoColorValue & 0x0F)];
|
||||||
for (uint8_t _y = 0; _y < displayScale; _y++){
|
|
||||||
renderMemory[(((y * (int)displayScale) + _y) * SDL_X_SIZE) + ((((x * (int)displayScale) * 8) + (i * (int)displayScale)) + _x)] = (videoValue & (128 >> i)) ? videoColorIndex[((videoColorValue & 0xF0) >> 4)] : videoColorIndex[(videoColorValue & 0x0F)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateVideo(){
|
void updateVideo(){
|
||||||
if (videoModified){
|
if (videoModified){
|
||||||
//sfVertexArray_clear(renderArray);
|
|
||||||
|
|
||||||
for (uint16_t y = 0; y < 256; y++){
|
for (uint16_t y = 0; y < 256; y++){
|
||||||
for (uint8_t x = 0; x < 48; x++){
|
for (uint8_t x = 0; x < 48; x++){
|
||||||
setPixels(x, (uint8_t)y);
|
setPixels(x, (uint8_t)y);
|
||||||
|
Loading…
Reference in New Issue
Block a user