mirror of
https://github.com/dschmenk/PLASMA.git
synced 2024-06-01 03:41:34 +00:00
Compare commits
2 Commits
8344f18612
...
82a1632bfd
Author | SHA1 | Date | |
---|---|---|---|
|
82a1632bfd | ||
|
db424e9fc7 |
|
@ -28,6 +28,10 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "lib6502.h"
|
#include "lib6502.h"
|
||||||
|
@ -37,6 +41,8 @@
|
||||||
typedef uint8_t byte;
|
typedef uint8_t byte;
|
||||||
typedef uint16_t word;
|
typedef uint16_t word;
|
||||||
|
|
||||||
|
struct termios org_tio;
|
||||||
|
|
||||||
void pfail(const char *msg)
|
void pfail(const char *msg)
|
||||||
{
|
{
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -83,21 +89,61 @@ int load(M6502 *mpu, word address, const char *path)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CFFA1 zero page addresses.
|
||||||
|
//
|
||||||
|
#define CFFADest 0x00
|
||||||
|
#define CFFAFileName 0x02
|
||||||
|
#define CFFAOldName 0x04
|
||||||
|
#define CFFAFileType 0x06
|
||||||
|
#define CFFAAuxType 0x07
|
||||||
|
#define CFFAFileSize 0x09
|
||||||
|
#define CFFAEntryPtr 0x0B
|
||||||
|
|
||||||
int cffa1(M6502 *mpu, word address, byte data)
|
int cffa1(M6502 *mpu, word address, byte data)
|
||||||
{
|
{
|
||||||
|
char *fileptr, filename[64];
|
||||||
|
int addr;
|
||||||
|
struct stat sbuf;
|
||||||
|
|
||||||
switch (mpu->registers->x)
|
switch (mpu->registers->x)
|
||||||
{
|
{
|
||||||
case 0x7A: /* perform keyboard scan */
|
case 0x02: /* quit */
|
||||||
mpu->registers->x= 0x00;
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 0x14: /* find dir entry */
|
||||||
|
addr = mpu->memory[CFFAFileName] | (mpu->memory[CFFAFileName + 1] << 8);
|
||||||
|
memset(filename, 0, 64);
|
||||||
|
strncpy(filename, (char *)(mpu->memory + addr + 1), mpu->memory[addr]);
|
||||||
|
strcat(filename, "#FE1000");
|
||||||
|
if (!(stat(filename, &sbuf)))
|
||||||
|
{
|
||||||
|
/* DirEntry @ $9100 */
|
||||||
|
mpu->memory[CFFAEntryPtr] = 0x00;
|
||||||
|
mpu->memory[CFFAEntryPtr + 1] = 0x91;
|
||||||
|
mpu->memory[0x9115] = sbuf.st_size;
|
||||||
|
mpu->memory[0x9116] = sbuf.st_size >> 8;
|
||||||
|
mpu->registers->a = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mpu->registers->a = -1;
|
||||||
|
break;
|
||||||
|
case 0x22: /* load file */
|
||||||
|
addr = mpu->memory[CFFAFileName] | (mpu->memory[CFFAFileName + 1] << 8);
|
||||||
|
memset(filename, 0, 64);
|
||||||
|
strncpy(filename, (char *)(mpu->memory + addr + 1), mpu->memory[addr]);
|
||||||
|
strcat(filename, "#FE1000");
|
||||||
|
addr = mpu->memory[CFFADest] | (mpu->memory[CFFADest + 1] << 8);
|
||||||
|
mpu->registers->a = load(mpu, addr, filename) - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
char state[64];
|
char state[64];
|
||||||
|
fprintf(stderr, "Unimplemented CFFA function: %02X\n", mpu->registers->x);
|
||||||
M6502_dump(mpu, state);
|
M6502_dump(mpu, state);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fprintf(stderr, "\nCFFA1 %s\n", state);
|
fprintf(stderr, "\nCFFA1 %s\n", state);
|
||||||
fail("ABORT");
|
pfail("ABORT");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -105,18 +151,38 @@ int cffa1(M6502 *mpu, word address, byte data)
|
||||||
}
|
}
|
||||||
|
|
||||||
int bye(M6502 *mpu, word addr, byte data) { exit(0); return 0; }
|
int bye(M6502 *mpu, word addr, byte data) { exit(0); return 0; }
|
||||||
int cout(M6502 *mpu, word addr, byte data) { putchar(mpu->registers->a); fflush(stdout); rts; }
|
int cout(M6502 *mpu, word addr, byte data) { if (mpu->registers->a == 0x8D) putchar('\n'); putchar(mpu->registers->a & 0x7F); fflush(stdout); rts; }
|
||||||
|
|
||||||
int rd6820kbdctl(M6502 *mpu, word addr, byte data) { return 0x80; }
|
unsigned keypending = 0;
|
||||||
|
unsigned char keypressed(void)
|
||||||
|
{
|
||||||
|
unsigned char cin;
|
||||||
|
if (read(STDIN_FILENO, &cin, 1) > 0)
|
||||||
|
keypending = cin | 0x80;
|
||||||
|
return keypending & 0x80;
|
||||||
|
}
|
||||||
|
unsigned char keyin(void)
|
||||||
|
{
|
||||||
|
unsigned char cin;
|
||||||
|
|
||||||
|
if (!keypending)
|
||||||
|
keypressed();
|
||||||
|
cin = keypending;
|
||||||
|
keypending = 0;
|
||||||
|
return cin;
|
||||||
|
}
|
||||||
|
int rd6820kbdctl(M6502 *mpu, word addr, byte data) { return keypressed(); }
|
||||||
int rd6820vidctl(M6502 *mpu, word addr, byte data) { return 0x00; }
|
int rd6820vidctl(M6502 *mpu, word addr, byte data) { return 0x00; }
|
||||||
int rd6820kbd(M6502 *mpu, word addr, byte data) { return getchar(); }
|
int rd6820kbd(M6502 *mpu, word addr, byte data) { return keyin(); }
|
||||||
int wr6820vid(M6502 *mpu, word addr, byte data) { putchar(data); fflush(stdout); return 0; }
|
int rd6820vid(M6502 *mpu, word addr, byte data) { return 0x80; }
|
||||||
|
int wr6820vid(M6502 *mpu, word addr, byte data) { if (data == 0x8D) putchar('\n'); putchar(data & 0x7F); fflush(stdout); return 0; }
|
||||||
|
|
||||||
int setTraps(M6502 *mpu)
|
int setTraps(M6502 *mpu)
|
||||||
{
|
{
|
||||||
/* Apple 1 memory-mapped IO */
|
/* Apple 1 memory-mapped IO */
|
||||||
M6502_setCallback(mpu, read, 0xD010, rd6820kbd);
|
M6502_setCallback(mpu, read, 0xD010, rd6820kbd);
|
||||||
M6502_setCallback(mpu, read, 0xD011, rd6820kbdctl);
|
M6502_setCallback(mpu, read, 0xD011, rd6820kbdctl);
|
||||||
|
M6502_setCallback(mpu, read, 0xD012, rd6820vid);
|
||||||
M6502_setCallback(mpu, write, 0xD012, wr6820vid);
|
M6502_setCallback(mpu, write, 0xD012, wr6820vid);
|
||||||
M6502_setCallback(mpu, read, 0xD013, rd6820vidctl);
|
M6502_setCallback(mpu, read, 0xD013, rd6820vidctl);
|
||||||
/* CFFA1 and ROM calls */
|
/* CFFA1 and ROM calls */
|
||||||
|
@ -126,18 +192,53 @@ int setTraps(M6502 *mpu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetInput(void)
|
||||||
|
{
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &org_tio);
|
||||||
|
}
|
||||||
|
void setRawInput(void)
|
||||||
|
{
|
||||||
|
struct termios termio;
|
||||||
|
|
||||||
|
// Save input settings.
|
||||||
|
tcgetattr(STDIN_FILENO, &termio); /* save current port settings */
|
||||||
|
memcpy(&org_tio, &termio, sizeof(struct termios));
|
||||||
|
termio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD;
|
||||||
|
termio.c_iflag = IGNPAR;
|
||||||
|
termio.c_oflag = 0;
|
||||||
|
termio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||||
|
termio.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||||
|
termio.c_cc[VMIN] = 0; /* non-blocking read */
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &termio);
|
||||||
|
atexit(resetInput);
|
||||||
|
}
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *interpfile = "A1PLASMA";
|
char *interpfile = "A1PLASMA#060280";
|
||||||
|
char *program= argv[0];
|
||||||
M6502 *mpu = M6502_new(0, 0, 0);
|
M6502 *mpu = M6502_new(0, 0, 0);
|
||||||
|
|
||||||
if (argc == 2)
|
while (++argv, --argc > 0)
|
||||||
interpfile = argv[1];
|
{
|
||||||
|
if (!strcmp(*argv, "-t")) mpu->flags |= M6502_SingleStep;
|
||||||
|
else
|
||||||
|
if (argv[0][0] != '-') interpfile = *argv;
|
||||||
|
else fprintf(stderr, "Usage: %s [-t] [interpreter file]", program);
|
||||||
|
}
|
||||||
if (!load(mpu, 0x280, interpfile))
|
if (!load(mpu, 0x280, interpfile))
|
||||||
pfail(interpfile);
|
pfail(interpfile);
|
||||||
|
setRawInput();
|
||||||
setTraps(mpu);
|
setTraps(mpu);
|
||||||
M6502_reset(mpu);
|
M6502_reset(mpu);
|
||||||
M6502_run(mpu);
|
mpu->registers->pc = 0x0280;
|
||||||
|
while (M6502_run(mpu))
|
||||||
|
{
|
||||||
|
char state[64];
|
||||||
|
char insn[64];
|
||||||
|
M6502_dump(mpu, state);
|
||||||
|
M6502_disassemble(mpu, mpu->registers->pc, insn);
|
||||||
|
printf("%s : %s\n", state, insn);
|
||||||
|
}
|
||||||
M6502_delete(mpu);
|
M6502_delete(mpu);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,7 +584,7 @@ enum {
|
||||||
tick(ticks); \
|
tick(ticks); \
|
||||||
fflush(stdout); \
|
fflush(stdout); \
|
||||||
fprintf(stderr, "\nundefined instruction %02X\n", memory[PC-1]); \
|
fprintf(stderr, "\nundefined instruction %02X\n", memory[PC-1]); \
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
#define phR(ticks, adrmode, R) \
|
#define phR(ticks, adrmode, R) \
|
||||||
fetch(); \
|
fetch(); \
|
||||||
|
@ -744,7 +744,7 @@ static void oops(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void M6502_run(M6502 *mpu)
|
int M6502_run(M6502 *mpu)
|
||||||
{
|
{
|
||||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||||
|
|
||||||
|
@ -768,9 +768,10 @@ void M6502_run(M6502 *mpu)
|
||||||
register void **itabp= &itab[0];
|
register void **itabp= &itab[0];
|
||||||
register void *tpc;
|
register void *tpc;
|
||||||
|
|
||||||
# define begin() fetch(); next()
|
//# define begin() fetch(); next()
|
||||||
|
# define begin() goto *(itabp[memory[PC++]])
|
||||||
# define fetch() tpc= itabp[memory[PC++]]
|
# define fetch() tpc= itabp[memory[PC++]]
|
||||||
# define next() goto *tpc
|
# define next() if (STEP) { PC--; externalise(); return 1; } goto *tpc
|
||||||
# define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) oops(); next()
|
# define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) oops(); next()
|
||||||
# define end()
|
# define end()
|
||||||
|
|
||||||
|
@ -778,7 +779,7 @@ void M6502_run(M6502 *mpu)
|
||||||
|
|
||||||
# define begin() for (;;) switch (memory[PC++]) {
|
# define begin() for (;;) switch (memory[PC++]) {
|
||||||
# define fetch()
|
# define fetch()
|
||||||
# define next() break
|
# define next() if (STEP) { externalise(); return 1; } break
|
||||||
# define dispatch(num, name, mode, cycles) case 0x##num: name(cycles, mode); next()
|
# define dispatch(num, name, mode, cycles) case 0x##num: name(cycles, mode); next()
|
||||||
# define end() }
|
# define end() }
|
||||||
|
|
||||||
|
@ -790,8 +791,9 @@ void M6502_run(M6502 *mpu)
|
||||||
byte A, X, Y, P, S;
|
byte A, X, Y, P, S;
|
||||||
M6502_Callback *readCallback= mpu->callbacks->read;
|
M6502_Callback *readCallback= mpu->callbacks->read;
|
||||||
M6502_Callback *writeCallback= mpu->callbacks->write;
|
M6502_Callback *writeCallback= mpu->callbacks->write;
|
||||||
|
unsigned int STEP;
|
||||||
|
|
||||||
# define internalise() A= mpu->registers->a; X= mpu->registers->x; Y= mpu->registers->y; P= mpu->registers->p; S= mpu->registers->s; PC= mpu->registers->pc
|
# define internalise() STEP=mpu->flags&M6502_SingleStep; A= mpu->registers->a; X= mpu->registers->x; Y= mpu->registers->y; P= mpu->registers->p; S= mpu->registers->s; PC= mpu->registers->pc
|
||||||
# define externalise() mpu->registers->a= A; mpu->registers->x= X; mpu->registers->y= Y; mpu->registers->p= P; mpu->registers->s= S; mpu->registers->pc= PC
|
# define externalise() mpu->registers->a= A; mpu->registers->x= X; mpu->registers->y= Y; mpu->registers->p= P; mpu->registers->s= S; mpu->registers->pc= PC
|
||||||
|
|
||||||
internalise();
|
internalise();
|
||||||
|
@ -809,6 +811,7 @@ void M6502_run(M6502 *mpu)
|
||||||
# undef end
|
# undef end
|
||||||
|
|
||||||
(void)oops;
|
(void)oops;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,14 +48,15 @@ struct _M6502
|
||||||
enum {
|
enum {
|
||||||
M6502_RegistersAllocated = 1 << 0,
|
M6502_RegistersAllocated = 1 << 0,
|
||||||
M6502_MemoryAllocated = 1 << 1,
|
M6502_MemoryAllocated = 1 << 1,
|
||||||
M6502_CallbacksAllocated = 1 << 2
|
M6502_CallbacksAllocated = 1 << 2,
|
||||||
|
M6502_SingleStep = 1 << 3
|
||||||
};
|
};
|
||||||
|
|
||||||
extern M6502 *M6502_new(M6502_Registers *registers, M6502_Memory memory, M6502_Callbacks *callbacks);
|
extern M6502 *M6502_new(M6502_Registers *registers, M6502_Memory memory, M6502_Callbacks *callbacks);
|
||||||
extern void M6502_reset(M6502 *mpu);
|
extern void M6502_reset(M6502 *mpu);
|
||||||
extern void M6502_nmi(M6502 *mpu);
|
extern void M6502_nmi(M6502 *mpu);
|
||||||
extern void M6502_irq(M6502 *mpu);
|
extern void M6502_irq(M6502 *mpu);
|
||||||
extern void M6502_run(M6502 *mpu);
|
extern int M6502_run(M6502 *mpu);
|
||||||
extern int M6502_disassemble(M6502 *mpu, uint16_t addr, char buffer[64]);
|
extern int M6502_disassemble(M6502 *mpu, uint16_t addr, char buffer[64]);
|
||||||
extern void M6502_dump(M6502 *mpu, char buffer[64]);
|
extern void M6502_dump(M6502 *mpu, char buffer[64]);
|
||||||
extern void M6502_delete(M6502 *mpu);
|
extern void M6502_delete(M6502 *mpu);
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
include "inc/cmdsys.plh"
|
include "inc/cmdsys.plh"
|
||||||
|
puts("a"); putln
|
||||||
|
puts("bb"); putln
|
||||||
|
puts("ccc"); putln
|
||||||
puts("Hello, world.\n")
|
puts("Hello, world.\n")
|
||||||
done
|
done
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const RELADDR = $1000
|
const RELADDR = $1000
|
||||||
const inbuff = $200
|
const inbuff = $01FF
|
||||||
const freemem = $0006
|
const freemem = $0006
|
||||||
//
|
//
|
||||||
// System flags: memory allocator screen holes.
|
// System flags: memory allocator screen holes.
|
||||||
|
|
|
@ -1098,7 +1098,9 @@ JUMP INY
|
||||||
JMP FETCHOP
|
JMP FETCHOP
|
||||||
A1CMD !SOURCE "vmsrc/apple/a1cmd.a"
|
A1CMD !SOURCE "vmsrc/apple/a1cmd.a"
|
||||||
SEGEND = *
|
SEGEND = *
|
||||||
VMINIT LDY #$10 ; INSTALL PAGE 0 FETCHOP ROUTINE
|
VMINIT LDX #$FE ; INIT STACK LEAVING ROOM FOR INBUFF SIZE
|
||||||
|
TXS
|
||||||
|
LDY #$10 ; INSTALL PAGE 0 FETCHOP ROUTINE
|
||||||
- LDA PAGE0-1,Y
|
- LDA PAGE0-1,Y
|
||||||
STA DROP-1,Y
|
STA DROP-1,Y
|
||||||
DEY
|
DEY
|
||||||
|
|
Loading…
Reference in New Issue
Block a user