initial commit
This commit is contained in:
commit
db560436c5
|
@ -0,0 +1,27 @@
|
||||||
|
# Snezzy
|
||||||
|
|
||||||
|
SNES emulator for awful people
|
||||||
|
|
||||||
|
## What?
|
||||||
|
|
||||||
|
you know how zsnes 0.150 is all kinds of awful? i want an emulator that is accurate enough to run most games, but is completely crippled in sound and video. i want to scream. i want to scream, and i want to be able to say it's my own damn fault
|
||||||
|
|
||||||
|
## What's wrong with you?
|
||||||
|
|
||||||
|
wish i knew
|
||||||
|
|
||||||
|
## How do I play games in it?
|
||||||
|
|
||||||
|
i ask myself this too!
|
||||||
|
|
||||||
|
short answer: thats the neat thing. you dont
|
||||||
|
|
||||||
|
long answer: build layla and create an instruction decode loop, write a memory remapper, and implement 96% of the opcodes in the 65816 emulator. next, create an emulator for the ricoh 5a22 extensions, the spc700, and the s-ppu. finally, send me your code because you just made an entire emulator! congratulations! you can play any game without expansion chips!
|
||||||
|
|
||||||
|
## What's the name mean?
|
||||||
|
|
||||||
|
snezzy: [see this twitter post](https://twitter.com/Lynntendo64/status/1479021585646473216)
|
||||||
|
|
||||||
|
layla: i was listening to [this song](https://www.youtube.com/watch?v=TngViNw2pOo) on loop when i started writing it
|
||||||
|
|
||||||
|
spencer: SPenCer. SPC
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
cc main.c -o bin/laylatest && cc howmany.c -o bin/howmany && bin/howmany && bin/laylatest
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "layla.c"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int c = 0;
|
||||||
|
for(int i = 0; i < 256; i++) c+=(!!(long)ll_opcodes[i]);
|
||||||
|
printf("%i opcodes complete (%f%% to native mode success!)\n", c, 0.390625 * c);
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
#include "layla.h"
|
||||||
|
|
||||||
|
uint8_t (*ll_read)(ll_cpu* c, uint32_t addr) = NULL;
|
||||||
|
void (*ll_write)(ll_cpu* c, uint32_t addr, uint8_t b) = NULL;
|
||||||
|
|
||||||
|
int ll_init_status = 0;
|
||||||
|
|
||||||
|
void ll_reg_read(uint8_t(*rdp)(ll_cpu* c, uint32_t addr)) {
|
||||||
|
ll_read = rdp;
|
||||||
|
ll_init_status |= 2;
|
||||||
|
if(ll_init_status == 6) ll_init_status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ll_reg_write(void(*wrp)(ll_cpu* c, uint32_t addr, uint8_t b)) {
|
||||||
|
ll_write = wrp;
|
||||||
|
ll_init_status |= 4;
|
||||||
|
if(ll_init_status == 6) ll_init_status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll_read16(ll_cpu* c, uint32_t addr) {
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ll_write16(ll_cpu* c, uint32_t addr, uint16_t w) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t llnop(ll_cpu* c) {}
|
||||||
|
|
||||||
|
uint16_t ll18(ll_cpu* c) {
|
||||||
|
c->P.f.C = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll1b(ll_cpu* c) {
|
||||||
|
if(c->e) {
|
||||||
|
if(c->SP.D.H != 1) exit(printf("LINE %s ERR\n", __LINE__));
|
||||||
|
c->SP.D.L = c->A.D.L;
|
||||||
|
}
|
||||||
|
else c->SP.F = c->A.F;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll38(ll_cpu* c) {
|
||||||
|
c->P.f.C = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll3b(ll_cpu* c) {
|
||||||
|
c->A.F = c->SP.F;
|
||||||
|
ll_setnz16(SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll58(ll_cpu* c) {
|
||||||
|
c->P.f.I = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll5b(ll_cpu* c) {
|
||||||
|
c->D.F = c->A.F;
|
||||||
|
ll_setnz16(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll78(ll_cpu* c) {
|
||||||
|
c->P.f.I = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll7b(ll_cpu* c) {
|
||||||
|
c->A.F = c->D.F;
|
||||||
|
ll_setnz16(A);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll98(ll_cpu* c) {
|
||||||
|
ll_trans(Y, A);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll9a(ll_cpu* c) {
|
||||||
|
// ll_trans sans status
|
||||||
|
if(c->P.f.XB) c->SP.D.L = c->X.D.L;
|
||||||
|
// TODO needed?
|
||||||
|
if(!c->e && c->P.f.XB) c->SP.D.H = 0;
|
||||||
|
else c->SP.F = c->X.F;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ll9b(ll_cpu* c) {
|
||||||
|
ll_trans(X, Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t lla8(ll_cpu* c) {
|
||||||
|
ll_trans(A, Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `llaa, you got me on my knees`
|
||||||
|
uint16_t llaa(ll_cpu* c) {
|
||||||
|
ll_trans(A, X);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t llb8(ll_cpu* c) {
|
||||||
|
c->P.f.V = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t llba(ll_cpu* c) {
|
||||||
|
ll_trans(SP, X);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t lld8(ll_cpu* c) {
|
||||||
|
c->P.f.D = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t lleb(ll_cpu* c) {
|
||||||
|
ll_swap(c->A.D.H, c->A.D.L);
|
||||||
|
ll_setnz8(A);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t llf8(ll_cpu* c) {
|
||||||
|
c->P.f.D = 1;
|
||||||
|
printf("DECIMAL UNIMPLEMENTED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t llfb(ll_cpu* c) {
|
||||||
|
c->e = c->P.f.C;
|
||||||
|
if(c->e) {
|
||||||
|
c->P.f.M = 1;
|
||||||
|
c->P.f.XB = 1;
|
||||||
|
c->X.D.H = 0;
|
||||||
|
c->Y.D.H = 0;
|
||||||
|
c->SP.D.H = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LL_E 0
|
||||||
|
// if negative, called opcode will return the number of cycles. else, use this
|
||||||
|
int ll_cycles[256] = {
|
||||||
|
//(YX) 0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 0
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 1
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 2
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 3
|
||||||
|
LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 4
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 5
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 6
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 7
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 8
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 9
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, // a
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, // b
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // c
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // d
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, 3, LL_E, LL_E, LL_E, LL_E, // e
|
||||||
|
LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E // f
|
||||||
|
};
|
||||||
|
|
||||||
|
ll_opcode ll_opcodes[256] = {
|
||||||
|
//(YX) 0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll18, NULL, NULL, &ll1b, NULL, NULL, NULL, NULL, // 1
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 2
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll38, NULL, NULL, &ll3b, NULL, NULL, NULL, NULL, // 3
|
||||||
|
NULL, NULL, &llnop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 4
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll58, NULL, NULL, &ll5b, NULL, NULL, NULL, NULL, // 5
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 6
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll78, NULL, NULL, &ll7b, NULL, NULL, NULL, NULL, // 7
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 8
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll98, &ll9b, NULL, NULL, NULL, NULL, NULL, NULL, // 9
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &lla8, NULL, &llaa, NULL, NULL, NULL, NULL, NULL, // a
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &llb8, NULL, &llba, NULL, NULL, NULL, NULL, NULL, // b
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // c
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &lld8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // d
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &llnop, &lleb, NULL, NULL, NULL, NULL, // e
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &llf8, NULL, NULL, &llfb, NULL, NULL, NULL, NULL // f
|
||||||
|
};
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef LAYLA_H
|
||||||
|
#define LAYLA_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PACK_STRUCT __attribute__((packed))
|
||||||
|
#define ll_swap(X, Y) X ^= Y ^= X ^= Y
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t C : 1;
|
||||||
|
uint8_t Z : 1;
|
||||||
|
uint8_t I : 1;
|
||||||
|
uint8_t D : 1;
|
||||||
|
uint8_t XB : 1;
|
||||||
|
uint8_t M : 1;
|
||||||
|
uint8_t V : 1;
|
||||||
|
uint8_t N : 1;
|
||||||
|
} PACK_STRUCT ll_status_internal;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint8_t byte;
|
||||||
|
ll_status_internal f;
|
||||||
|
} ll_status;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t L;
|
||||||
|
uint8_t H;
|
||||||
|
} ll_reg_HL;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint16_t F;
|
||||||
|
ll_reg_HL D;
|
||||||
|
} ll_reg;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// bools? whats that, a bowl spoon?
|
||||||
|
uint8_t e : 1;
|
||||||
|
uint8_t DB;
|
||||||
|
uint8_t PB;
|
||||||
|
ll_status P;
|
||||||
|
ll_reg A;
|
||||||
|
ll_reg X;
|
||||||
|
ll_reg Y;
|
||||||
|
ll_reg D;
|
||||||
|
ll_reg SP;
|
||||||
|
ll_reg PC;
|
||||||
|
void* data;
|
||||||
|
} ll_cpu;
|
||||||
|
|
||||||
|
typedef uint16_t(*ll_opcode)(ll_cpu*);
|
||||||
|
|
||||||
|
#define ll_setnz16(DEST) \
|
||||||
|
c->P.f.N = c->DEST.F >> 15; \
|
||||||
|
c->P.f.Z = (c->DEST.F == 0)
|
||||||
|
|
||||||
|
#define ll_setnz8(DEST) \
|
||||||
|
c->P.f.N = c->DEST.D.L >> 7; \
|
||||||
|
c->P.f.Z = (c->DEST.D.L == 0)
|
||||||
|
|
||||||
|
#define ll_trans(SRC, DEST) \
|
||||||
|
if(c->P.f.XB) { \
|
||||||
|
c->DEST.D.L = c->SRC.D.L; \
|
||||||
|
ll_setnz8(DEST); \
|
||||||
|
} else { \
|
||||||
|
c->DEST.F = c->SRC.F; \
|
||||||
|
ll_setnz16(DEST); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "layla.c"
|
||||||
|
int main() {
|
||||||
|
printf("sizeof ll_status: %u\n", sizeof(ll_status));
|
||||||
|
ll_reg b;
|
||||||
|
b.F = 0xFFEE;
|
||||||
|
printf("%02X\n", b.D.H);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <spencer.c>
|
||||||
|
|
||||||
|
uint8_t mmr(uint8_t reg, uint8_t d, uint8_t rw) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
spc_cpu s;
|
||||||
|
spc_init(&s, malloc(0x10000), &mmr);
|
||||||
|
// TODO copy in new spc data
|
||||||
|
while(1) {
|
||||||
|
printf( "WAIT: %u\n"
|
||||||
|
"\tPC: 0x%04X\n"
|
||||||
|
"\tSP: 0x%02X\n"
|
||||||
|
"\tA: 0x%02X\n"
|
||||||
|
"\tX: 0x%02X\n"
|
||||||
|
"\tY: 0x%02X\n"
|
||||||
|
,
|
||||||
|
s.wait,
|
||||||
|
s.PC,
|
||||||
|
s.SP,
|
||||||
|
s.A,
|
||||||
|
s.X,
|
||||||
|
s.Y
|
||||||
|
);
|
||||||
|
int r = spc_loop(&s);
|
||||||
|
if(r) exit(printf("error\n"));
|
||||||
|
}
|
||||||
|
return printf("stub\n");
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
SOURCES=main.c
|
||||||
|
OUTPUT=spctest
|
||||||
|
FLAGS=-I.
|
|
@ -0,0 +1,275 @@
|
||||||
|
Mnemonic Code Bytes Cyc Operation NVPBHIZC
|
||||||
|
|
||||||
|
NOP 00 1 2 do nothing ........
|
||||||
|
|
||||||
|
CLRP 20 1 2 P = 0 ..0.....
|
||||||
|
|
||||||
|
INC X 3D 1 2 X++ N.....Z.
|
||||||
|
|
||||||
|
SETP 40 1 2 P = 1 ..1.....
|
||||||
|
|
||||||
|
MOV X, A 5D 1 2 X = A N.....Z.
|
||||||
|
|
||||||
|
CLRC 60 1 2 C = 0 .......0
|
||||||
|
|
||||||
|
SETC 80 1 2 C = 1 .......1
|
||||||
|
|
||||||
|
EI A0 1 3 I = 1 .....1..
|
||||||
|
|
||||||
|
INC A BC 1 2 A++ N.....Z.
|
||||||
|
|
||||||
|
DI C0 1 3 I = 0 .....0..
|
||||||
|
|
||||||
|
CLRV E0 1 2 V = 0, H = 0 .0..0...
|
||||||
|
|
||||||
|
INC Y FC 1 2 Y++ N.....Z.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TCALL 0 01 1 8 CALL [$FFDE] ........
|
||||||
|
SET1 d.0 02 2 4 d.0 = 1 ........
|
||||||
|
BBS d.0, r 03 3 5/7 PC+=r if d.0 == 1 ........
|
||||||
|
OR A, d 04 2 3 A = A | (d) N.....Z.
|
||||||
|
OR A, !a 05 3 4 A = A | (a) N.....Z.
|
||||||
|
OR A, (X) 06 1 3 A = A | (X) N.....Z.
|
||||||
|
OR A, [d+X] 07 2 6 A = A | ([d+X]) N.....Z.
|
||||||
|
OR A, #i 08 2 2 A = A | i N.....Z.
|
||||||
|
OR dd, ds 09 3 6 (dd) = (dd) | (ds) N.....Z.
|
||||||
|
OR1 C, m.b 0A 3 5 C = C | (m.b) .......C
|
||||||
|
ASL d 0B 2 4 Left shift (d) as above N.....ZC
|
||||||
|
ASL !a 0C 3 5 Left shift (a) as above N.....ZC
|
||||||
|
PUSH PSW 0D 1 4 (SP--) = Flags ........
|
||||||
|
TSET1 !a 0E 3 6 (a) = (a)|A, ZN as for A-(a) N.....Z.
|
||||||
|
BRK 0F 1 8 Push PC and Flags, PC = [$FFDE] ...1.0..
|
||||||
|
BPL r 10 2 2/4 PC+=r if N == 0 ........
|
||||||
|
TCALL 1 11 1 8 CALL [$FFDC] ........
|
||||||
|
CLR1 d.0 12 2 4 d.0 = 0 ........
|
||||||
|
BBC d.0, r 13 3 5/7 PC+=r if d.0 == 0 ........
|
||||||
|
OR A, d+X 14 2 4 A = A | (d+X) N.....Z.
|
||||||
|
OR A, !a+X 15 3 5 A = A | (a+X) N.....Z.
|
||||||
|
OR A, !a+Y 16 3 5 A = A | (a+Y) N.....Z.
|
||||||
|
OR A, [d]+Y 17 2 6 A = A | ([d]+Y) N.....Z.
|
||||||
|
OR d, #i 18 3 5 (d) = (d) | i N.....Z.
|
||||||
|
OR (X), (Y) 19 1 5 (X) = (X) | (Y) N.....Z.
|
||||||
|
DECW d 1A 2 6 Word (d)-- N.....Z.
|
||||||
|
ASL d+X 1B 2 5 Left shift (d+X) as above N.....ZC
|
||||||
|
ASL A 1C 1 2 Left shift A: high->C, 0->low N.....ZC
|
||||||
|
DEC X 1D 1 2 X-- N.....Z.
|
||||||
|
CMP X, !a 1E 3 4 X - (a) N.....ZC
|
||||||
|
JMP [!a+X] 1F 3 6 PC = [a+X] ........
|
||||||
|
TCALL 2 21 1 8 CALL [$FFDA] ........
|
||||||
|
SET1 d.1 22 2 4 d.1 = 1 ........
|
||||||
|
BBS d.1, r 23 3 5/7 PC+=r if d.1 == 1 ........
|
||||||
|
AND A, d 24 2 3 A = A & (d) N.....Z.
|
||||||
|
AND A, !a 25 3 4 A = A & (a) N.....Z.
|
||||||
|
AND A, (X) 26 1 3 A = A & (X) N.....Z.
|
||||||
|
AND A, [d+X] 27 2 6 A = A & ([d+X]) N.....Z.
|
||||||
|
AND A, #i 28 2 2 A = A & i N.....Z.
|
||||||
|
AND dd, ds 29 3 6 (dd) = (dd) & (ds) N.....Z.
|
||||||
|
OR1 C, /m.b 2A 3 5 C = C | ~(m.b) .......C
|
||||||
|
ROL d 2B 2 4 Left shift (d) as above N.....ZC
|
||||||
|
ROL !a 2C 3 5 Left shift (a) as above N.....ZC
|
||||||
|
PUSH A 2D 1 4 (SP--) = A ........
|
||||||
|
CBNE d, r 2E 3 5/7 CMP A, (d) then BNE ........
|
||||||
|
BRA r 2F 2 4 PC+=r ........
|
||||||
|
BMI r 30 2 2/4 PC+=r if N == 1 ........
|
||||||
|
TCALL 3 31 1 8 CALL [$FFD8] ........
|
||||||
|
CLR1 d.1 32 2 4 d.1 = 0 ........
|
||||||
|
BBC d.1, r 33 3 5/7 PC+=r if d.1 == 0 ........
|
||||||
|
AND A, d+X 34 2 4 A = A & (d+X) N.....Z.
|
||||||
|
AND A, !a+X 35 3 5 A = A & (a+X) N.....Z.
|
||||||
|
AND A, !a+Y 36 3 5 A = A & (a+Y) N.....Z.
|
||||||
|
AND A, [d]+Y 37 2 6 A = A & ([d]+Y) N.....Z.
|
||||||
|
AND d, #i 38 3 5 (d) = (d) & i N.....Z.
|
||||||
|
AND (X), (Y) 39 1 5 (X) = (X) & (Y) N.....Z.
|
||||||
|
INCW d 3A 2 6 Word (d)++ N.....Z.
|
||||||
|
ROL d+X 3B 2 5 Left shift (d+X) as above N.....ZC
|
||||||
|
ROL A 3C 1 2 Left shift A: low=C, C=high N.....ZC
|
||||||
|
CMP X, d 3E 2 3 X - (d) N.....ZC
|
||||||
|
CALL !a 3F 3 8 (SP--)=PCh, (SP--)=PCl, PC=a ........
|
||||||
|
TCALL 4 41 1 8 CALL [$FFD6] ........
|
||||||
|
SET1 d.2 42 2 4 d.2 = 1 ........
|
||||||
|
BBS d.2, r 43 3 5/7 PC+=r if d.2 == 1 ........
|
||||||
|
EOR A, d 44 2 3 A = A EOR (d) N.....Z.
|
||||||
|
EOR A, !a 45 3 4 A = A EOR (a) N.....Z.
|
||||||
|
EOR A, (X) 46 1 3 A = A EOR (X) N.....Z.
|
||||||
|
EOR A, [d+X] 47 2 6 A = A EOR ([d+X]) N.....Z.
|
||||||
|
EOR A, #i 48 2 2 A = A EOR i N.....Z.
|
||||||
|
EOR dd, ds 49 3 6 (dd) = (dd) EOR (ds) N.....Z.
|
||||||
|
AND1 C, m.b 4A 3 4 C = C & (m.b) .......C
|
||||||
|
LSR d 4B 2 4 Right shift (d) as above N.....ZC
|
||||||
|
LSR !a 4C 3 5 Right shift (a) as above N.....ZC
|
||||||
|
PUSH X 4D 1 4 (SP--) = X ........
|
||||||
|
TCLR1 !a 4E 3 6 (a) = (a)&~A, ZN as for A-(a) N.....Z.
|
||||||
|
PCALL u 4F 2 6 CALL $FF00+u ........
|
||||||
|
BVC r 50 2 2/4 PC+=r if V == 0 ........
|
||||||
|
TCALL 5 51 1 8 CALL [$FFD4] ........
|
||||||
|
CLR1 d.2 52 2 4 d.2 = 0 ........
|
||||||
|
BBC d.2, r 53 3 5/7 PC+=r if d.2 == 0 ........
|
||||||
|
EOR A, d+X 54 2 4 A = A EOR (d+X) N.....Z.
|
||||||
|
EOR A, !a+X 55 3 5 A = A EOR (a+X) N.....Z.
|
||||||
|
EOR A, !a+Y 56 3 5 A = A EOR (a+Y) N.....Z.
|
||||||
|
EOR A, [d]+Y 57 2 6 A = A EOR ([d]+Y) N.....Z.
|
||||||
|
EOR d, #i 58 3 5 (d) = (d) EOR i N.....Z.
|
||||||
|
EOR (X), (Y) 59 1 5 (X) = (X) EOR (Y) N.....Z.
|
||||||
|
CMPW YA, d 5A 2 4 YA - (d) N.....ZC
|
||||||
|
LSR d+X 5B 2 5 Right shift (d+X) as above N.....ZC
|
||||||
|
LSR A 5C 1 2 Right shift A: 0->high, low->C N.....ZC
|
||||||
|
CMP Y, !a 5E 3 4 Y - (a) N.....ZC
|
||||||
|
JMP !a 5F 3 3 PC = a ........
|
||||||
|
TCALL 6 61 1 8 CALL [$FFD2] ........
|
||||||
|
SET1 d.3 62 2 4 d.3 = 1 ........
|
||||||
|
BBS d.3, r 63 3 5/7 PC+=r if d.3 == 1 ........
|
||||||
|
CMP A, d 64 2 3 A - (d) N.....ZC
|
||||||
|
CMP A, !a 65 3 4 A - (a) N.....ZC
|
||||||
|
CMP A, (X) 66 1 3 A - (X) N.....ZC
|
||||||
|
CMP A, [d+X] 67 2 6 A - ([d+X]) N.....ZC
|
||||||
|
CMP A, #i 68 2 2 A - i N.....ZC
|
||||||
|
CMP dd, ds 69 3 6 (dd) - (ds) N.....ZC
|
||||||
|
AND1 C, /m.b 6A 3 4 C = C & ~(m.b) .......C
|
||||||
|
ROR d 6B 2 4 Right shift (d) as above N.....ZC
|
||||||
|
ROR !a 6C 3 5 Right shift (a) as above N.....ZC
|
||||||
|
PUSH Y 6D 1 4 (SP--) = Y ........
|
||||||
|
DBNZ d, r 6E 3 5/7 (d)-- then JNZ ........
|
||||||
|
RET 6F 1 5 Pop PC ........
|
||||||
|
BVS r 70 2 2/4 PC+=r if V == 1 ........
|
||||||
|
TCALL 7 71 1 8 CALL [$FFD0] ........
|
||||||
|
CLR1 d.3 72 2 4 d.3 = 0 ........
|
||||||
|
BBC d.3, r 73 3 5/7 PC+=r if d.3 == 0 ........
|
||||||
|
CMP A, d+X 74 2 4 A - (d+X) N.....ZC
|
||||||
|
CMP A, !a+X 75 3 5 A - (a+X) N.....ZC
|
||||||
|
CMP A, !a+Y 76 3 5 A - (a+Y) N.....ZC
|
||||||
|
CMP A, [d]+Y 77 2 6 A - ([d]+Y) N.....ZC
|
||||||
|
CMP d, #i 78 3 5 (d) - i N.....ZC
|
||||||
|
CMP (X), (Y) 79 1 5 (X) - (Y) N.....ZC
|
||||||
|
ADDW YA, d 7A 2 5 YA = YA + (d), H on high byte NV..H.ZC
|
||||||
|
ROR d+X 7B 2 5 Right shift (d+X) as above N.....ZC
|
||||||
|
ROR A 7C 1 2 Right shift A: high=C, C=low N.....ZC
|
||||||
|
MOV A, X 7D 1 2 A = X N.....Z.
|
||||||
|
CMP Y, d 7E 2 3 Y - (d) N.....ZC
|
||||||
|
RET1 7F 1 6 Pop Flags, PC NVPBHIZC
|
||||||
|
TCALL 8 81 1 8 CALL [$FFCE] ........
|
||||||
|
SET1 d.4 82 2 4 d.4 = 1 ........
|
||||||
|
BBS d.4, r 83 3 5/7 PC+=r if d.4 == 1 ........
|
||||||
|
ADC A, d 84 2 3 A = A+(d)+C NV..H.ZC
|
||||||
|
ADC A, !a 85 3 4 A = A+(a)+C NV..H.ZC
|
||||||
|
ADC A, (X) 86 1 3 A = A+(X)+C NV..H.ZC
|
||||||
|
ADC A, [d+X] 87 2 6 A = A+([d+X])+C NV..H.ZC
|
||||||
|
ADC A, #i 88 2 2 A = A+i+C NV..H.ZC
|
||||||
|
ADC dd, ds 89 3 6 (dd) = (dd)+(d)+C NV..H.ZC
|
||||||
|
EOR1 C, m.b 8A 3 5 C = C EOR (m.b) .......C
|
||||||
|
DEC d 8B 2 4 (d)-- N.....Z.
|
||||||
|
DEC !a 8C 3 5 (a)-- N.....Z.
|
||||||
|
MOV Y, #i 8D 2 2 Y = i N.....Z.
|
||||||
|
POP PSW 8E 1 4 Flags = (++SP) NVPBHIZC
|
||||||
|
MOV d, #i 8F 3 5 (d) = i (read) ........
|
||||||
|
BCC r 90 2 2/4 PC+=r if C == 0 ........
|
||||||
|
TCALL 9 91 1 8 CALL [$FFCC] ........
|
||||||
|
CLR1 d.4 92 2 4 d.4 = 0 ........
|
||||||
|
BBC d.4, r 93 3 5/7 PC+=r if d.4 == 0 ........
|
||||||
|
ADC A, d+X 94 2 4 A = A+(d+X)+C NV..H.ZC
|
||||||
|
ADC A, !a+X 95 3 5 A = A+(a+X)+C NV..H.ZC
|
||||||
|
ADC A, !a+Y 96 3 5 A = A+(a+Y)+C NV..H.ZC
|
||||||
|
ADC A, [d]+Y 97 2 6 A = A+([d]+Y)+C NV..H.ZC
|
||||||
|
ADC d, #i 98 3 5 (d) = (d)+i+C NV..H.ZC
|
||||||
|
ADC (X), (Y) 99 1 5 (X) = (X)+(Y)+C NV..H.ZC
|
||||||
|
SUBW YA, d 9A 2 5 YA = YA - (d), H on high byte NV..H.ZC
|
||||||
|
DEC d+X 9B 2 5 (d+X)-- N.....Z.
|
||||||
|
DEC A 9C 1 2 A-- N.....Z.
|
||||||
|
MOV X, SP 9D 1 2 X = SP N.....Z.
|
||||||
|
DIV YA, X 9E 1 12 A=YA/X, Y=mod(YA,X) NV..H.Z.
|
||||||
|
XCN A 9F 1 5 A = (A>>4) | (A<<4) N.....Z.
|
||||||
|
|
||||||
|
|
||||||
|
TCALL 10 A1 1 8 CALL [$FFCA] ........
|
||||||
|
SET1 d.5 A2 2 4 d.5 = 1 ........
|
||||||
|
BBS d.5, r A3 3 5/7 PC+=r if d.5 == 1 ........
|
||||||
|
SBC A, d A4 2 3 A = A-(d)-!C NV..H.ZC
|
||||||
|
SBC A, !a A5 3 4 A = A-(a)-!C NV..H.ZC
|
||||||
|
SBC A, (X) A6 1 3 A = A-(X)-!C NV..H.ZC
|
||||||
|
SBC A, [d+X] A7 2 6 A = A-([d+X])-!C NV..H.ZC
|
||||||
|
SBC A, #i A8 2 2 A = A-i-!C NV..H.ZC
|
||||||
|
SBC dd, ds A9 3 6 (dd) = (dd)-(ds)-!C NV..H.ZC
|
||||||
|
MOV1 C, m.b AA 3 4 C = (m.b) .......C
|
||||||
|
INC d AB 2 4 (d)++ N.....Z.
|
||||||
|
INC !a AC 3 5 (a)++ N.....Z.
|
||||||
|
CMP Y, #i AD 2 2 Y - i N.....ZC
|
||||||
|
POP A AE 1 4 A = (++SP) ........
|
||||||
|
MOV (X)+, A AF 1 4 (X++) = A (no read) ........
|
||||||
|
BCS r B0 2 2/4 PC+=r if C == 1 ........
|
||||||
|
TCALL 11 B1 1 8 CALL [$FFC8] ........
|
||||||
|
CLR1 d.5 B2 2 4 d.5 = 0 ........
|
||||||
|
BBC d.5, r B3 3 5/7 PC+=r if d.5 == 0 ........
|
||||||
|
SBC A, d+X B4 2 4 A = A-(d+X)-!C NV..H.ZC
|
||||||
|
SBC A, !a+X B5 3 5 A = A-(a+X)-!C NV..H.ZC
|
||||||
|
SBC A, !a+Y B6 3 5 A = A-(a+Y)-!C NV..H.ZC
|
||||||
|
SBC A, [d]+Y B7 2 6 A = A-([d]+Y)-!C NV..H.ZC
|
||||||
|
SBC d, #i B8 3 5 (d) = (d)-i-!C NV..H.ZC
|
||||||
|
SBC (X), (Y) B9 1 5 (X) = (X)-(Y)-!C NV..H.ZC
|
||||||
|
MOVW YA, d BA 2 5 YA = word (d) N.....Z.
|
||||||
|
INC d+X BB 2 5 (d+X)++ N.....Z.
|
||||||
|
MOV SP, X BD 1 2 SP = X ........
|
||||||
|
DAS A BE 1 3 decimal adjust for subtraction N.....ZC
|
||||||
|
MOV A, (X)+ BF 1 4 A = (X++) N.....Z.
|
||||||
|
TCALL 12 C1 1 8 CALL [$FFC6] ........
|
||||||
|
SET1 d.6 C2 2 4 d.6 = 1 ........
|
||||||
|
BBS d.6, r C3 3 5/7 PC+=r if d.6 == 1 ........
|
||||||
|
MOV d, A C4 2 4 (d) = A (read) ........
|
||||||
|
MOV !a, A C5 3 5 (a) = A (read) ........
|
||||||
|
MOV (X), A C6 1 4 (X) = A (read) ........
|
||||||
|
MOV [d+X], A C7 2 7 ([d+X]) = A (read) ........
|
||||||
|
CMP X, #i C8 2 2 X - i N.....ZC
|
||||||
|
MOV !a, X C9 3 5 (a) = X (read) ........
|
||||||
|
MOV1 m.b, C CA 3 6 (m.b) = C ........
|
||||||
|
MOV d, Y CB 2 4 (d) = Y (read) ........
|
||||||
|
MOV !a, Y CC 3 5 (a) = Y (read) ........
|
||||||
|
MOV X, #i CD 2 2 X = i N.....Z.
|
||||||
|
POP X CE 1 4 X = (++SP) ........
|
||||||
|
MUL YA CF 1 9 YA = Y * A, NZ on Y only N.....Z.
|
||||||
|
BNE r D0 2 2/4 PC+=r if Z == 0 ........
|
||||||
|
TCALL 13 D1 1 8 CALL [$FFC4] ........
|
||||||
|
CLR1 d.6 D2 2 4 d.6 = 0 ........
|
||||||
|
BBC d.6, r D3 3 5/7 PC+=r if d.6 == 0 ........
|
||||||
|
MOV d+X, A D4 2 5 (d+X) = A (read) ........
|
||||||
|
MOV !a+X, A D5 3 6 (a+X) = A (read) ........
|
||||||
|
MOV !a+Y, A D6 3 6 (a+Y) = A (read) ........
|
||||||
|
MOV [d]+Y, A D7 2 7 ([d]+Y) = A (read) ........
|
||||||
|
MOV d, X D8 2 4 (d) = X (read) ........
|
||||||
|
MOV d+Y, X D9 2 5 (d+Y) = X (read) ........
|
||||||
|
MOVW d, YA DA 2 5 word (d) = YA (read low only) ........
|
||||||
|
MOV d+X, Y DB 2 5 (d+X) = Y (read) ........
|
||||||
|
DEC Y DC 1 2 Y-- N.....Z.
|
||||||
|
MOV A, Y DD 1 2 A = Y N.....Z.
|
||||||
|
CBNE d+X, r DE 3 6/8 CMP A, (d+X) then BNE ........
|
||||||
|
DAA A DF 1 3 decimal adjust for addition N.....ZC
|
||||||
|
TCALL 14 E1 1 8 CALL [$FFC2] ........
|
||||||
|
SET1 d.7 E2 2 4 d.7 = 1 ........
|
||||||
|
BBS d.7, r E3 3 5/7 PC+=r if d.7 == 1 ........
|
||||||
|
MOV A, d E4 2 3 A = (d) N.....Z.
|
||||||
|
MOV A, !a E5 3 4 A = (a) N.....Z.
|
||||||
|
MOV A, (X) E6 1 3 A = (X) N.....Z.
|
||||||
|
MOV A, [d+X] E7 2 6 A = ([d+X]) N.....Z.
|
||||||
|
MOV A, #i E8 2 2 A = i N.....Z.
|
||||||
|
MOV X, !a E9 3 4 X = (a) N.....Z.
|
||||||
|
NOT1 m.b EA 3 5 m.b = ~m.b ........
|
||||||
|
MOV Y, d EB 2 3 Y = (d) N.....Z.
|
||||||
|
MOV Y, !a EC 3 4 Y = (a) N.....Z.
|
||||||
|
NOTC ED 1 3 C = !C .......C
|
||||||
|
POP Y EE 1 4 Y = (++SP) ........
|
||||||
|
SLEEP EF 1 ? Halts the processor ........
|
||||||
|
BEQ r F0 2 2/4 PC+=r if Z == 1 ........
|
||||||
|
TCALL 15 F1 1 8 CALL [$FFC0] ........
|
||||||
|
CLR1 d.7 F2 2 4 d.7 = 0 ........
|
||||||
|
BBC d.7, r F3 3 5/7 PC+=r if d.7 == 0 ........
|
||||||
|
MOV A, d+X F4 2 4 A = (d+X) N.....Z.
|
||||||
|
MOV A, !a+X F5 3 5 A = (a+X) N.....Z.
|
||||||
|
MOV A, !a+Y F6 3 5 A = (a+Y) N.....Z.
|
||||||
|
MOV A, [d]+Y F7 2 6 A = ([d]+Y) N.....Z.
|
||||||
|
MOV X, d F8 2 3 X = (d) N.....Z.
|
||||||
|
MOV X, d+Y F9 2 4 X = (d+Y) N.....Z.
|
||||||
|
MOV dd, ds FA 3 5 (dd) = (ds) (no read) ........
|
||||||
|
MOV Y, d+X FB 2 4 Y = (d+X) N.....Z.
|
||||||
|
MOV Y, A FD 1 2 Y = A N.....Z.
|
||||||
|
DBNZ Y, r FE 2 4/6 Y-- then JNZ ........
|
||||||
|
STOP FF 1 ? Halts the processor ........
|
Binary file not shown.
|
@ -0,0 +1,152 @@
|
||||||
|
#include <spencer.h>
|
||||||
|
|
||||||
|
// needs memset
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// needs printf
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void spc_init(spc_cpu* s, void* mem, uint8_t(*mmr)(uint8_t, uint8_t, uint8_t)) {
|
||||||
|
memset(s, 0, sizeof(spc_cpu));
|
||||||
|
s->mmr = mmr;
|
||||||
|
s->mem = mem;
|
||||||
|
s->initialized = 0x59C700;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t spc_ipl[0x40] = {
|
||||||
|
0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
|
||||||
|
0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5,
|
||||||
|
0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA,
|
||||||
|
0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t spc_r(spc_cpu* s, uint16_t p) {
|
||||||
|
if((p >= 0xF0 && p <= 0xF7) || (p >= 0xFA && p <= 0xFF)) return s->mmr(p - 0xF0, 0, S_R);
|
||||||
|
if(p >= 0xFFC0 && s->mmr(0xF1, 0, S_R) >> 7) return spc_ipl[p - 0xFFC0];
|
||||||
|
return s->mem[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
void spc_w(spc_cpu* s, uint16_t p, uint8_t d) {
|
||||||
|
if((p >= 0xF0 && p <= 0xF7) || (p >= 0xFA && p <= 0xFF)) {
|
||||||
|
s->mmr(p - 0xF0, d, S_W);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->mem[p] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is bad
|
||||||
|
#define spc_im8(C, O) (spc_r(C, C->PC + 1 + O))
|
||||||
|
|
||||||
|
// this is not okay
|
||||||
|
#define spc_im16(C) ((((uint16_t)spc_im8(C, 1)) << 8) | spc_im8(C, 0))
|
||||||
|
|
||||||
|
// with code like this all these opcodes are illegal opcodes
|
||||||
|
#define spc_dp(C, O) ((((uint16_t)spc_getp(C)) << 8) | (uint8_t)O)
|
||||||
|
|
||||||
|
#define spc_sp(C, O) (0x100 | (uint8_t)O)
|
||||||
|
|
||||||
|
#define spc_push(C, O) spc_w(C, 0x100 + ((uint8_t)C->SP--), O)
|
||||||
|
|
||||||
|
#define spc_pull(C) spc_r(C, C->SP++)
|
||||||
|
|
||||||
|
#define NUL 0
|
||||||
|
int spc_cycles[256] = { // -1: length returned by spc_eval
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||||
|
2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 0
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 1
|
||||||
|
2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 2
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, // 3
|
||||||
|
2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 4
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, // 5
|
||||||
|
2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 6
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 7
|
||||||
|
2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 8
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 9
|
||||||
|
3, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // a
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, NUL, // b
|
||||||
|
3, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // c
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // d
|
||||||
|
2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // e
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, NUL // f
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t spc_len[256] = {
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 0
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 1
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 2
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, // 3
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 4
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, // 5
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 6
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 7
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 8
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 9
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // a
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, NUL, // b
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // c
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // d
|
||||||
|
1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // e
|
||||||
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, NUL // f
|
||||||
|
};
|
||||||
|
|
||||||
|
int spc_eval(spc_cpu* s, int* err) {
|
||||||
|
int cycles = 0;
|
||||||
|
switch(spc_r(s, s->PC)) {
|
||||||
|
case 0x00:
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
spc_unsetp(s);
|
||||||
|
break;
|
||||||
|
case 0xBC:
|
||||||
|
spc_inc(s, s->A);
|
||||||
|
break;
|
||||||
|
case 0x3D:
|
||||||
|
spc_inc(s, s->X);
|
||||||
|
break;
|
||||||
|
case 0x40:
|
||||||
|
spc_setp(s);
|
||||||
|
break;
|
||||||
|
case 0x5D:
|
||||||
|
spc_trans(s, s->X, s->A);
|
||||||
|
break;
|
||||||
|
case 0x60:
|
||||||
|
spc_unsetc(s);
|
||||||
|
break;
|
||||||
|
case 0x80:
|
||||||
|
spc_setc(s);
|
||||||
|
break;
|
||||||
|
case 0xA0:
|
||||||
|
spc_seti(s);
|
||||||
|
break;
|
||||||
|
case 0xC0:
|
||||||
|
spc_unseti(s);
|
||||||
|
break;
|
||||||
|
case 0xE0:
|
||||||
|
spc_unsetv(s);
|
||||||
|
spc_unseth(s);
|
||||||
|
break;
|
||||||
|
case 0xFC:
|
||||||
|
spc_inc(s, s->Y);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unimplemented opcode: 0x%02X\n", spc_r(s, s->PC));
|
||||||
|
*err = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s->PC += spc_len[spc_r(s, s->PC)];
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spc_loop(spc_cpu* s) {
|
||||||
|
if(s->initialized != 0x59C700) return !printf("SPENCER UNINITIALIZED\n") - 1;
|
||||||
|
int err = 0;
|
||||||
|
if(s->wait == 0) {
|
||||||
|
printf("-- EVAL --\n");
|
||||||
|
int w = spc_cycles[spc_r(s, s->PC)], c = spc_eval(s, &err);
|
||||||
|
if(w == -1) s->wait = c;
|
||||||
|
else s->wait = w;
|
||||||
|
s->wait--;
|
||||||
|
} else s->wait--;
|
||||||
|
return err;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
#ifndef SPENCER_H
|
||||||
|
#define SPENCER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// mmr flags
|
||||||
|
#define S_R 1 // read
|
||||||
|
#define S_W 0 // write
|
||||||
|
#define S_I 2 // internal (for internal emulator function)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t A, X, Y, SP, P; // 1 byte registers
|
||||||
|
uint16_t PC; // 2 byte registers
|
||||||
|
uint8_t* mem; // 0x10000 bytes
|
||||||
|
|
||||||
|
/* MMR arguments:
|
||||||
|
*
|
||||||
|
* width description
|
||||||
|
* -------------------------
|
||||||
|
* u8 | register number (0-15)
|
||||||
|
* u8 | data to write (if reading anything is fine)
|
||||||
|
* u8 | S_R to read, S_W to write
|
||||||
|
*/
|
||||||
|
uint8_t(*mmr)(uint8_t, uint8_t, uint8_t);
|
||||||
|
unsigned int wait;
|
||||||
|
unsigned int initialized;
|
||||||
|
uint8_t sleeping;
|
||||||
|
} spc_cpu;
|
||||||
|
|
||||||
|
#define spc_getn(CPU) (CPU->P >> 7)
|
||||||
|
#define spc_getv(CPU) ((CPU->P >> 6) & 1)
|
||||||
|
#define spc_getp(CPU) ((CPU->P >> 5) & 1)
|
||||||
|
#define spc_getb(CPU) ((CPU->P >> 4) & 1)
|
||||||
|
#define spc_geth(CPU) ((CPU->P >> 3) & 1)
|
||||||
|
#define spc_geti(CPU) ((CPU->P >> 2) & 1)
|
||||||
|
#define spc_getz(CPU) ((CPU->P >> 1) & 1)
|
||||||
|
#define spc_getc(CPU) (CPU->P & 1)
|
||||||
|
|
||||||
|
#define spc_setn(CPU) CPU->P |= 0x80
|
||||||
|
#define spc_setv(CPU) CPU->P |= 0x40
|
||||||
|
#define spc_setp(CPU) CPU->P |= 0x20
|
||||||
|
#define spc_setb(CPU) CPU->P |= 0x10
|
||||||
|
#define spc_seth(CPU) CPU->P |= 0x08
|
||||||
|
#define spc_seti(CPU) CPU->P |= 0x04
|
||||||
|
#define spc_setz(CPU) CPU->P |= 0x02
|
||||||
|
#define spc_setc(CPU) CPU->P |= 0x01
|
||||||
|
|
||||||
|
#define spc_unsetn(CPU) CPU->P &= ~0x80
|
||||||
|
#define spc_unsetv(CPU) CPU->P &= ~0x40
|
||||||
|
#define spc_unsetp(CPU) CPU->P &= ~0x20
|
||||||
|
#define spc_unsetb(CPU) CPU->P &= ~0x10
|
||||||
|
#define spc_unseth(CPU) CPU->P &= ~0x08
|
||||||
|
#define spc_unseti(CPU) CPU->P &= ~0x04
|
||||||
|
#define spc_unsetz(CPU) CPU->P &= ~0x02
|
||||||
|
#define spc_unsetc(CPU) CPU->P &= ~0x01
|
||||||
|
|
||||||
|
#define spc_sbn(c, d) c->P = (c->P & 0x7F) | (d & 0x80)
|
||||||
|
#define spc_sbz(c, d) c->P = (c->P & 0xFD) | (!d << 1)
|
||||||
|
|
||||||
|
#define spc_inc(c, d) d++; spc_sbn(c, d); spc_sbz(c, d)
|
||||||
|
#define spc_trans(c, a, b) a = b; spc_sbn(c, a); spc_sbz(c, a)
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue