Skip to content

Instantly share code, notes, and snippets.

@pgavlin pgavlin/gtemu.c
Last active Apr 27, 2019

Embed
What would you like to do?
Emulating a GT1 on a GT1 using a very, very slightly modified gtemu.c
#define NULL 0
typedef unsigned uint16_t;
typedef unsigned char uint8_t;
void cls();
void putchar(uint8_t c);
typedef struct { // TTL state that the CPU controls
uint16_t PC;
uint8_t IR, D, AC, X, Y, OUT, undef;
} CpuState;
#define ROMSIZE 16
#define RAMSIZE 16
uint8_t ROM0[ROMSIZE] = {
0x10, 0x14, 0x18, 0xfc, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
uint8_t ROM1[ROMSIZE] = {
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define C(c) (c | 0x80)
uint8_t RAM[RAMSIZE] = {
C('H'), C('e'), C('l'), C('l'), C('o'), C(','), C(' '), C('w'), C('o'), C('r'), C('l'), C('d'), C('!'), 0x80, 0, 0,
};
uint8_t IN=0xff;
CpuState cpuCycle(const CpuState S)
{
int ins, mod, bus, W, J, incX, B;
uint8_t lo, hi, *to, ALU;
uint16_t addr;
CpuState T = S; // New state is old state unless something changes
T.IR = ROM0[S.PC & (ROMSIZE-1)]; // Instruction Fetch
T.D = ROM1[S.PC & (ROMSIZE-1)];
ins = S.IR >> 5; // Instruction
mod = (S.IR >> 2) & 7; // Addressing mode (or condition)
bus = S.IR&3; // Busmode
W = (ins == 6); // Write instruction?
J = (ins == 7); // Jump instruction?
lo=S.D, hi=0, *to=NULL; // Mode Decoder
incX=0;
if (!J)
switch (mod) {
#define E(p) (W?0:p) // Disable AC and OUT loading during RAM write
case 0: to=E(&T.AC); break;
case 1: to=E(&T.AC); lo=S.X; break;
case 2: to=E(&T.AC); hi=S.Y; break;
case 3: to=E(&T.AC); lo=S.X; hi=S.Y; break;
case 4: to= &T.X; break;
case 5: to= &T.Y; break;
case 6: to=E(&T.OUT); break;
case 7: to=E(&T.OUT); lo=S.X; hi=S.Y; incX=1; break;
}
addr = (hi << 8) | lo;
B = S.undef; // Data Bus
switch (bus) {
case 0: B=S.D; break;
case 1: if (!W) B = RAM[(addr&0x7fff) & (RAMSIZE-1)]; break;
case 2: B=S.AC; break;
case 3: B=IN; break;
}
if (W) RAM[(addr&0x7fff) & (RAMSIZE-1)] = B; // Random Access Memory
// Arithmetic and Logic Unit
switch (ins) {
case 0: ALU = B; break; // LD
case 1: ALU = S.AC & B; break; // ANDA
case 2: ALU = S.AC | B; break; // ORA
case 3: ALU = S.AC ^ B; break; // XORA
case 4: ALU = S.AC + B; break; // ADDA
case 5: ALU = S.AC - B; break; // SUBA
case 6: ALU = S.AC; break; // ST
case 7: ALU = -S.AC; break; // Bcc/JMP
}
if (to) *to = ALU; // Load value into register
if (incX) T.X = S.X + 1; // Increment X
T.PC = S.PC + 1; // Next instruction
if (J) {
if (mod != 0) { // Conditional branch within page
int cond = (S.AC>>7) + ((S.AC==0) << 1);
if (mod & (1 << cond)) // 74153
T.PC = (S.PC & 0xff00) | B;
} else
T.PC = (S.Y << 8) | B; // Unconditional far jump
}
return T;
}
void main()
{
CpuState S, T;
int strobe;
cls();
S.PC = 0; // MCP100 Power-On Reset
for (;;) {
T = cpuCycle(S); // Update CPU
strobe = (T.OUT & 0x80) - (S.OUT & 0x80); // "write strobe"
if (strobe > 0) {
if (T.OUT == 0x80) {
break; // kill the simulator on NUL
}
putchar(T.OUT & 0x7f);
}
S=T;
}
}
#define Sys_Draw4_30 0x04d4
#define SYS_VDrawBits_134 0x04e1
#define sysfn ((unsigned*)(void*)0x0022u)
#define sysargs ((unsigned char*)(void*)0x0024u)
#define sysargsw ((unsigned*)(void*)0x0024u)
#define giga_xres 160
#define giga_yres 120
#define font32up ((unsigned char*)(void*)0x0700)
#define font82up ((unsigned char*)(void*)0x0800)
#define vram ((unsigned char*)(void*)0x0800)
#define rand ((unsigned char*)(void*)0x0006)
#define xbounds 0x9f
#define ybounds 0x77
void cls() {
unsigned ii, jj;
unsigned char aa, bb;
*sysfn = Sys_Draw4_30;
sysargsw[0] = 0;
sysargsw[1] = 0;
aa = 0x08, bb = 0x7f;
jj = giga_yres / 2;
do {
sysargs[4] = 0;
ii = giga_xres / 4;
do {
sysargs[5] = aa;
__syscall(0xff);
sysargs[5] = bb;
__syscall(0xff);
sysargs[4] += 4;
} while (--ii, ii > 0);
aa++, bb--;
} while (--jj, jj > 0);
}
static unsigned char* pos = vram;
void putchar(unsigned char c) {
unsigned char* bitmap;
unsigned i;
i = c - 32;
if (i < 50) {
bitmap = font32up;
} else {
i -= 50;
bitmap = font82up;
}
bitmap = &bitmap[(i << 2) + i];
sysargs[0] = 0x3f;
sysargsw[2] = (unsigned)(void*)pos;
*sysfn = SYS_VDrawBits_134;
for (i = 5; i > 0; --i, bitmap++) {
sysargs[2] = __lookup(0, bitmap) ^ 0xff;
__syscall(203);
sysargs[4]++;
}
pos += 6;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.