1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-12-01 03:18:05 +11:00
collapseos/emul/hw/rc2014/classic.c
Virgil Dupras 9216057db8 emul/hw: add TI-84+ emulator
I implement the screen using XCB which is much more friendly
than z80e's SDL+CMake for development machines that want to install
minimal dependencies (for example, a port-less OpenBSD rig).
2020-01-01 22:48:01 -05:00

127 lines
2.9 KiB
C

/* RC2014 classic
*
* - 8K of ROM in range 0x0000-0x2000
* - 32K of RAM in range 0x8000-0xffff
* - ACIA in ports 0x80 (ctl) and 0x81 (data)
*
* ACIA is hooked to stdin/stdout. CTRL+D exits when in TTY mode.
*/
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include "../../emul.h"
#include "acia.h"
#define RAMSTART 0x8000
#define ACIA_CTL_PORT 0x80
#define ACIA_DATA_PORT 0x81
#define MAX_ROMSIZE 0x2000
static ACIA acia;
static uint8_t iord_acia_ctl()
{
return acia_ctl_rd(&acia);
}
static uint8_t iord_acia_data()
{
return acia_data_rd(&acia);
}
static void iowr_acia_ctl(uint8_t val)
{
acia_ctl_wr(&acia, val);
}
static void iowr_acia_data(uint8_t val)
{
acia_data_wr(&acia, val);
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: ./classic /path/to/rom\n");
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Can't open %s\n", argv[1]);
return 1;
}
Machine *m = emul_init();
m->ramstart = RAMSTART;
int i = 0;
int c;
while ((c = fgetc(fp)) != EOF && i < MAX_ROMSIZE) {
m->mem[i++] = c & 0xff;
}
pclose(fp);
if (i == MAX_ROMSIZE) {
fprintf(stderr, "ROM image too large.\n");
return 1;
}
bool tty = isatty(fileno(stdin));
struct termios term, saved_term;
if (tty) {
// Turn echo off: the shell takes care of its own echoing.
if (tcgetattr(0, &term) == -1) {
printf("Can't setup terminal.\n");
return 1;
}
saved_term = term;
term.c_lflag &= ~ECHO;
term.c_lflag &= ~ICANON;
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 0;
tcsetattr(0, TCSADRAIN, &term);
}
acia_init(&acia);
m->iord[ACIA_CTL_PORT] = iord_acia_ctl;
m->iord[ACIA_DATA_PORT] = iord_acia_data;
m->iowr[ACIA_CTL_PORT] = iowr_acia_ctl;
m->iowr[ACIA_DATA_PORT] = iowr_acia_data;
char tosend = 0;
while (emul_step()) {
// Do we have an interrupt?
if (acia_has_irq(&acia)) {
Z80INT(&m->cpu, 0);
}
// Is the RC2014 transmitting?
if (acia_hastx(&acia)) {
putchar(acia_read(&acia));
fflush(stdout);
}
// Do we have something to send?
if (!tosend) {
char c;
if (read(fileno(stdin), &c, 1) == 1) {
if (c == 4) { // CTRL+D
// Stop here
break;
}
tosend = c;
} else if (!tty) {
// This means we reached EOF
break;
}
}
if (tosend && !acia_hasrx(&acia)) {
acia_write(&acia, tosend);
tosend = 0;
}
}
if (tty) {
printf("Done!\n");
tcsetattr(0, TCSADRAIN, &saved_term);
emul_printdebug();
}
return 0;
}