2014-12-07 15:36:42 +00:00
|
|
|
#include <assert.h>
|
2014-12-04 17:43:58 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
2014-12-07 08:37:16 +00:00
|
|
|
#include <stdlib.h>
|
2014-12-04 17:43:58 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2014-12-07 08:37:16 +00:00
|
|
|
static uint8_t mem[0x10000];
|
|
|
|
static uint8_t key = 0x80;
|
2014-12-07 18:11:03 +00:00
|
|
|
static char keyString[] = "10 print \"hello\"\r20 end\rlist\rrun\r";
|
|
|
|
static uint32_t keyCount = 0;
|
2014-12-07 08:37:16 +00:00
|
|
|
static uint8_t last = 0x00;
|
2014-12-04 17:43:58 +00:00
|
|
|
|
2014-12-07 04:54:47 +00:00
|
|
|
void prn(int c) {
|
2014-12-07 18:38:58 +00:00
|
|
|
uint32_t fp;
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs %0, r12": "=r"(fp));
|
2014-12-07 08:37:16 +00:00
|
|
|
fprintf(stderr, "### $%02x ###\n", c);
|
|
|
|
fflush(stderr);
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs r12, %0":: "r"(fp));
|
2014-12-07 04:54:47 +00:00
|
|
|
}
|
|
|
|
|
2014-12-07 15:36:42 +00:00
|
|
|
void cpu6502_dump(uint32_t pc, uint32_t a, uint32_t x, uint32_t y,
|
|
|
|
uint32_t sp, uint32_t sr) {
|
2014-12-07 19:19:05 +00:00
|
|
|
/*
|
2014-12-07 18:38:58 +00:00
|
|
|
uint32_t fp;
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs %0, r12": "=r"(fp));
|
2014-12-07 15:46:38 +00:00
|
|
|
assert(pc < 0x10000);
|
2014-12-07 15:36:42 +00:00
|
|
|
assert(a < 0x100);
|
|
|
|
assert(x < 0x100);
|
|
|
|
assert(y < 0x100);
|
|
|
|
assert(sr < 0x100);
|
|
|
|
assert(0x100 <= sp && sp < 0x200);
|
2014-12-07 08:37:16 +00:00
|
|
|
fprintf(stderr, "*** dump *** PC=$%04x A=$%02x X=$%02x Y=$%02x SP=$%02x "
|
|
|
|
"NV-B_DIZC=%d%d-%d_%d%d%d%d\n",
|
2014-12-07 17:43:05 +00:00
|
|
|
pc, a, x, y, sp & 0xff, (sr >> 7) & 1, (sr >> 6) & 1, (sr >> 4) & 1,
|
2014-12-07 08:37:16 +00:00
|
|
|
(sr >> 3) & 1, (sr >> 2) & 1, (sr >> 1) & 1, sr & 1);
|
|
|
|
fflush(stderr);
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs r12, %0":: "r"(fp));
|
2014-12-07 19:19:05 +00:00
|
|
|
*/
|
2014-12-04 17:43:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t cpu6502_load(uint16_t addr) {
|
2014-12-07 18:38:58 +00:00
|
|
|
uint32_t fp;
|
2014-12-07 08:37:16 +00:00
|
|
|
uint8_t result = 0;
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs %0, r12": "=r"(fp));
|
2014-12-07 08:37:16 +00:00
|
|
|
if (0x0400 <= addr && addr <= 0x7ff) {
|
|
|
|
// Fake text VRAM.
|
|
|
|
result = mem[addr];
|
|
|
|
} else if ((0x0300 <= addr && addr <= 0x03ff) ||
|
|
|
|
(0x0900 <= addr && addr <= 0x0fff)) {
|
|
|
|
// Fake memory impl to make it run on low memory chip.
|
|
|
|
result = last;
|
|
|
|
} else if (0x1000 <= addr & addr < 0xbfff) {
|
|
|
|
// Bus error due to minimum memory installation.
|
|
|
|
return 0xff;
|
|
|
|
fprintf(stdout, "\e[1;1Hinvalid load $%04x\n", addr);
|
|
|
|
fflush(stdout);
|
|
|
|
abort();
|
|
|
|
} else if (0xc000 <= addr & addr < 0xcfff) {
|
|
|
|
// I/O emulation.
|
2014-12-07 18:11:03 +00:00
|
|
|
if (0xc000 == addr) {
|
|
|
|
keyCount++;
|
2014-12-07 19:19:05 +00:00
|
|
|
if (keyCount < 0x800) {
|
2014-12-07 18:11:03 +00:00
|
|
|
result = key;
|
2014-12-07 19:19:05 +00:00
|
|
|
} else if (keyCount & 0xff) {
|
|
|
|
result = key;
|
|
|
|
} else {
|
|
|
|
uint32_t n = (keyCount - 0x800) >> 8;
|
|
|
|
if (n < sizeof(keyString))
|
|
|
|
key = keyString[n] | 0x80;
|
2014-12-07 18:11:03 +00:00
|
|
|
result = key;
|
|
|
|
}
|
|
|
|
} else if (0xc010 == addr) {
|
2014-12-07 08:37:16 +00:00
|
|
|
key &= 0x7f;
|
2014-12-07 18:11:03 +00:00
|
|
|
result = 0;
|
|
|
|
}
|
2014-12-07 08:37:16 +00:00
|
|
|
} else {
|
|
|
|
// Installed memory.
|
|
|
|
result = mem[addr];
|
|
|
|
}
|
|
|
|
fprintf(stderr, "load $%04x => $%02x\n", addr, result);
|
|
|
|
fflush(stderr);
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs r12, %0":: "r"(fp));
|
2014-12-07 08:37:16 +00:00
|
|
|
return result;
|
2014-12-04 17:43:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void cpu6502_store(uint16_t addr, uint8_t data) {
|
2014-12-07 18:38:58 +00:00
|
|
|
uint32_t fp;
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs %0, r12": "=r"(fp));
|
2014-12-07 08:37:16 +00:00
|
|
|
if (0x0400 <= addr && addr <= 0x7ff) {
|
|
|
|
// Fake text VRAM.
|
|
|
|
char ascii[0x40] =
|
|
|
|
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?";
|
|
|
|
mem[addr] = data;
|
|
|
|
int y = (addr - 0x400) >> 7;
|
|
|
|
int x = addr & 0x7f;
|
|
|
|
if (x >= 0x50) {
|
|
|
|
x -= 0x50;
|
|
|
|
y += 0x10;
|
|
|
|
} else if (x >= 0x28) {
|
|
|
|
x -= 0x28;
|
|
|
|
y += 0x08;
|
|
|
|
}
|
2014-12-07 19:19:05 +00:00
|
|
|
if (y < 24) {
|
|
|
|
fprintf(stdout, "\e[%d;%dH%c", y + 7, x + 1, ascii[data & 0x3f]);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
2014-12-07 08:37:16 +00:00
|
|
|
} else if ((0x0300 <= addr && addr <= 0x03ff) ||
|
|
|
|
(0x0900 <= addr && addr <= 0x0fff)) {
|
|
|
|
// Fake memory impl to make it run on low memory chip.
|
|
|
|
last = data;
|
2014-12-07 19:19:05 +00:00
|
|
|
} else if (0x1000 <= addr & addr < 0xbfff) {
|
2014-12-07 08:37:16 +00:00
|
|
|
// Bus error due to minimum memory installation.
|
|
|
|
return;
|
|
|
|
fprintf(stdout, "\e[1;1Hinvalid store $%04x\n", addr);
|
|
|
|
fflush(stdout);
|
|
|
|
abort();
|
2014-12-07 19:19:05 +00:00
|
|
|
} else if (0xc000 <= addr & addr < 0xcfff) {
|
|
|
|
// I/O emulation.
|
|
|
|
if (0xc000 == addr)
|
|
|
|
key = data;
|
2014-12-07 08:37:16 +00:00
|
|
|
} else {
|
|
|
|
// Installed memory.
|
|
|
|
mem[addr] = data;
|
|
|
|
}
|
|
|
|
fprintf(stderr, "store $%04x <= $%02x\n", addr, data);
|
|
|
|
fflush(stderr);
|
2014-12-07 07:35:46 +00:00
|
|
|
__asm__("movs r12, %0":: "r"(fp));
|
2014-12-04 17:43:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
FILE* fp = fopen("applebasic.rom", "rb");
|
2014-12-07 15:21:06 +00:00
|
|
|
//FILE* fp = fopen("apple2o.rom", "rb");
|
2014-12-04 17:43:58 +00:00
|
|
|
memset(mem, 0, 0x10000);
|
|
|
|
fread(&mem[0xd000], 1, 0x3000, fp);
|
|
|
|
fclose(fp);
|
|
|
|
cpu6502_reset();
|
2014-12-07 08:37:16 +00:00
|
|
|
fprintf(stderr, "quit: $%04x\n", cpu6502_run());
|
2014-12-04 17:43:58 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|