Commit 8c226e88 authored by Vladimir Serbinenko's avatar Vladimir Serbinenko
Browse files

Move main loop to a separate file

parent d75aeb21
......@@ -49,11 +49,11 @@ UTILS = maketape readtape
SRCS = access.c boot.c branch.c conf.c covox.c double.c ea.c itab.c \
main.c service.c ui.c scr-sdl.c scr.c timer.c tape.c disk.c mouse.c printer.c \
single.c weird.c tty.c io.c timing.c sound.c disas.c serial.c bkplip.c \
terakdisk.c synth.c emu2149.c sdlsound.c sdltty.c
terakdisk.c synth.c emu2149.c standalone.c sdlsound.c sdltty.c
OBJS = access.o boot.o branch.o conf.o covox.o double.o ea.o itab.o icon.o \
main.o service.o ui.o scr-sdl.o scr.o timer.o tape.o disk.o mouse.o printer.o \
single.o weird.o tty.o io.o timing.o sound.o disas.o serial.o bkplip.o \
terakdisk.o synth.o emu2149.o sdlsound.o sdltty.o
terakdisk.o synth.o emu2149.o standalone.c sdlsound.o sdltty.o
INCS = defines.h scr.h conf.h emu2149.h emutypes.h
USRCS = readtape.c maketape.c pngtorgba.c
TEXTS = README.html configure.in icon.c
......
......@@ -492,12 +492,15 @@ typedef struct {
} disk_t;
extern unsigned long pending_interrupts;
void ev_fire( int priority );
void sim_init(void);
int checkpoint(d_word pc);
extern int breakpoint;
extern unsigned char change_req;
extern unsigned char param_change_line;
extern unsigned char req_page[512], req_palette[512];
extern int cybuf[1024];
extern int cybufidx;
void intr_hand(void);
#endif
......@@ -31,7 +31,6 @@
#include "defines.h"
#include "scr.h"
#include "conf.h"
#include <SDL/SDL.h>
#include "intl.h"
#include <locale.h>
#include <sys/time.h>
......@@ -43,19 +42,6 @@
struct bk_state current_state;
const char * printer_file = 0;
char init_path[BUFSIZ];
char game_path[512];
unsigned int hasgame;
unsigned int refreshtime = 0;
unsigned int hasexit = 0;
/* Some games require the BASIC ROM to be loaded
* in memory before they are playable so i had to make
* this little hack. */
#define LOAD_GAME() if (hasgame == 1) {\
refreshtime++; \
if (refreshtime > 64) flag = 0; }
/*
* At start-up, bkmodel == 0, 1, or 2 means BK-0010, 3 means BK-0011M.
......@@ -66,8 +52,6 @@ if (refreshtime > 64) flag = 0; }
char * romdir = "./roms"; /* default ROM path */
const char *const monitor10rom = "MONIT10.ROM";
char * focal10rom = "FOCAL10.ROM";
char * basic10rom = "BASIC10.ROM";
const char *const diskrom = "DISK_327.ROM";
const char *const bos11rom = "B11M_BOS.ROM";
const char *const bos11extrom = "B11M_EXT.ROM";
......@@ -83,299 +67,8 @@ const char * floppyD = "D.img";
* Command line flags and variables.
*/
flag_t aflag; /* autoboot flag */
flag_t covoxflag; /* covox flag */
flag_t synthflag; /* AY-3-8910 flag */
flag_t plipflag; /* PLIP flag */
flag_t traceflag; /* print all instruction addresses */
FILE * tracefile; /* trace goes here */
flag_t turboflag; /* "Turbo" mode with doubled clock speed */
/*
* main()
*/
int
main( argc, argv )
int argc;
char **argv;
{
/* Gettext stuff */
setlocale (LC_ALL, "");
bindtextdomain ("bk", "/usr/share/locale");
textdomain ("bk");
init_config();
aflag = 1; /* auto boot */
nflag = 1; /* enable sound */
hasgame = 0;
/* nothing is connected to the port by default, use ~/.bkrc */
if ( args( argc, argv ) < 0 ) {
fprintf( stderr, _("Usage: %s [options]\n"), argv[0] );
fprintf( stderr, _(" -0 BK-0010\n") );
fprintf( stderr, _(" -1 BK-0010.01\n") );
fprintf( stderr, _(" -2 BK-0010.01 + FDD\n") );
fprintf( stderr, _(" -3 BK-0011M + FDD\n") );
fprintf( stderr, _(" -K Terak 8510/a\n") );
fprintf( stderr, _(" -A<file> A: floppy image file or device (instead of %s)\n"), floppyA );
fprintf( stderr, _(" -B<file> B: floppy image file or device (instead of %s)\n"), floppyB );
fprintf( stderr, _(" -C<file> C: floppy image file or device (instead of %s)\n"), floppyC );
fprintf( stderr, _(" -D<file> D: floppy image file or device (instead of %s)\n"), floppyD );
fprintf( stderr, _(" -a Do not boot automatically\n") );
fprintf( stderr, _(" -c Color mode\n") );
fprintf( stderr, _(" -n Disable sound \n") );
fprintf( stderr, _(" -v Enable Covox\n") );
fprintf( stderr, _(" -y Enable AY-3-8910\n") );
fprintf( stderr, _(" -m Enable mouse\n") );
fprintf( stderr, _(" -S Full speed mode\n") );
fprintf( stderr, _(" -s \"TURBO\" mode (Real overclocked BK)\n") );
fprintf( stderr, _(" -R<file> Specify an alternative ROM file @ 120000.\n") );
fprintf( stderr, _(" -r<file> Specify an alternative ROM file @ 160000.\n") );
fprintf( stderr, _(" -T Disable reading from tape\n") );
fprintf( stderr, _(" -t Trace mode, -t<file> - to file\n") );
fprintf( stderr, _(" -l<path> Enable printer and specify output pathname\n") );
fprintf( stderr, _("\n\
The default ROM files are stored in\n\
%s or the directory specified\n\
by the environment variable BK_PATH.\n"), romdir );
fprintf( stderr, _("\nExamples:.\n") );
fprintf( stderr, _(" 'bk -R./BK.ROM' - Use custom ROM\n") );
fprintf( stderr, _(" 'bk -a -n -f' - Developer's mode\n") );
fprintf( stderr, _(" 'bk -c' - Gaming mode\n\n") );
exit( -1 );
}
atexit(SDL_Quit);
atexit(disk_finish);
/* Set ROM configuration */
if (getenv("BK_PATH"))
{
romdir = getenv("BK_PATH");
}
switch( bkmodel ) {
case 0: /* BK0010 */
rompath10 = monitor10rom;
rompath12 = focal10rom;
rompath16 = 0;
TICK_RATE = 3000000;
break;
case 1: /* BK0010.01 */
rompath10 = monitor10rom;
rompath12 = basic10rom;
rompath16 = 0;
TICK_RATE = 3000000;
break;
case 2: /* BK0010.01+FDD */
rompath10 = monitor10rom;
rompath12 = 0;
rompath16 = diskrom;
TICK_RATE = 3000000;
break;
case 3: /* BK-0011M */
case 9: /* Terak 8510/a */
rompath10 = rompath12 = rompath16 = 0;
TICK_RATE = 4000000;
break;
case 4: /* Slow BK-0011M */
rompath10 = rompath12 = rompath16 = 0;
TICK_RATE = 3000000;
break;
default: /* Unknown ROM configuration */
fprintf( stderr, _("Unknown BK model. Bailing out.\n"), argv[0] );
exit( -1 );
}
/* Turn on the "TURBO" mode */
if ( turboflag ) {
TICK_RATE = (TICK_RATE * 2);
}
printf( _("Initializing SDL.\n") );
if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)==-1)) {
printf( _("Could not initialize SDL: %s.\n"), SDL_GetError());
exit(-1);
}
fprintf(stderr, _("Welcome to \"Elektronika BK\" emulator!\n\n") );
showemuhelp(); /* print a short emulator help message */
showbkhelp(); /* print a short help message */
printf( _("SDL initialized.\n") );
/* Convert BK model to 0010/0011 flag */
fake_disk &= bkmodel >= 2;
terak = bkmodel == 9;
bkmodel = bkmodel >= 3;
tty_open(); /* initialize the tty stuff */
ev_init(); /* initialize the event system */
sim_init(); /* ...the simulated cpu */
mem_init(); /* ...main memory */
scr_init(); /* video display */
boot_init(); /* ROM blocks */
if (terak) {
// setup_terak();
} else {
if (mouseflag)
plug_mouse();
if (printer_file)
plug_printer();
if (covoxflag)
plug_covox();
if (synthflag)
plug_synth();
if (plipflag)
plug_bkplip();
}
q_reset(); /* ...any devices */
/* Starting frame rate */
frame_delay = TICK_RATE/25;
half_frame_delay = TICK_RATE/50;
if (terak) {
pdp.regs[PC] = 0173000;
} else {
lc_word(0177716, &pdp.regs[PC]);
pdp.regs[PC] &= 0177400;
}
if (init_path[0]) {
tracefile = fopen(init_path, "w");
}
/*if ( aflag )
{
run( 1 );
ui();
} else {
ui();
}*/
while(!hasexit)
{
run( 1 ); /* go for it */
if (hasgame == 1)
{
extern ui_load(const char *);
ui_load(game_path);
ui_start( "1000", 1 );
hasgame = 0;
}
else if (hasexit == 0)
{
ui();
}
}
disk_finish();
Quit_SDL();
return 0; /* get out of here */
}
/*
* args()
*/
args( argc, argv )
int argc;
char **argv;
{
char *farg;
char **narg;
narg = argv;
while ( --argc ) {
narg++;
farg = *narg;
if ( *farg++ == '-' ) {
switch( *farg ) {
case '0': case '1': case '2': case '3': case '4':
bkmodel = *farg - '0';
break;
case 'K':
bkmodel = 9;
// Terak has no sound yet, turn sound off
nflag = 0;
break;
case 'A':
floppyA = *++farg ? farg : (argc--,*++narg);
break;
case 'B':
floppyB = *++farg ? farg : (argc--,*++narg);
break;
case 'C':
floppyC = *++farg ? farg : (argc--,*++narg);
break;
case 'D':
floppyD = *++farg ? farg : (argc--,*++narg);
break;
case 'a':
aflag = 0;
break;
case 'c':
cflag = 1;
break;
case 'n':
nflag = 0;
break;
case 'v':
covoxflag = 1;
break;
case 'y':
synthflag = 1;
break;
case 'm':
mouseflag = *(farg+1) ? *(farg+1)-'0' : 1;
break;
case 'p':
plipflag = 1;
break;
case 'S':
fullspeed = 1;
break;
case 's':
turboflag = 1;
break;
case 'R':
rompath12 = *++farg ? farg : (argc--,*++narg);
break;
case 'r':
rompath16 = *++farg ? farg : (argc--,*++narg);
break;
case 'T':
tapeflag = 1;
break;
case 't':
traceflag = 1;
if (*++farg)
strcpy(init_path, farg);
break;
case 'g':
hasgame = 1;
if (*++farg)
strcpy(game_path, farg);
break;
case 'l':
printer_file = *++farg ? farg : (argc--,*++narg);;
break;
default:
return -1;
/*NOTREACHED*/
break;
}
} else {
return -1;
}
}
return 0;
}
static int checkpoint(d_word pc);
const char *rompath10, *rompath12, *rompath16;
......@@ -397,53 +90,6 @@ sim_init()
pdp_ram_map = 0x0000ffff;
}
/*
* run() - Run instructions (either just one or until something bad
* happens). Lots of nasty stuff to set up the terminal and the
* execution timing.
*/
int
run( int flag )
{
register pdp_regs *p = &pdp; /* pointer to global struct */
struct timeval start_time; /* system time of simulation start */
struct timeval stop_time; /* system time of simulation end */
double expired, speed; /* for statistics information */
/*
* Set up the terminal cbreak i/o and start running.
*/
gettimeofday( &start_time, 0 );
run_2( p, flag );
gettimeofday( &stop_time, 0 );
if (!flag)
return;
/*
* Compute execution statistics and print it.
*/
expired = ((double) stop_time.tv_sec) +
(((double) stop_time.tv_usec) / 1000000.0 );
expired -= ((double) start_time.tv_sec) +
(((double) start_time.tv_usec) / 1000000.0 );
if ( expired != 0.0 )
speed = (((double)p->total) / expired );
else
speed = 0.0;
fprintf( stderr, _("Instructions executed: %d\n"), p->total );
fprintf( stderr, _("Simulation rate: %.5g instructions per second\n"),
speed );
fprintf( stderr, _("BK speed: %.5g instructions per second\n"),
(double) p->total * TICK_RATE / ticks );
p->total = 0;
}
double ticks_screen = 0.0;
extern unsigned long pending_interrupts;
int cybuf[1024];
int cybufidx = 0;
......@@ -454,194 +100,6 @@ addtocybuf(int val) {
cybufidx = (cybufidx+1) % 1024;
}
int
run_2( p, flag )
register pdp_regs *p;
int flag;
{
register int result; /* result of execution */
int result2; /* result of error handling */
extern void intr_hand(); /* SIGINT handler */
register unsigned priority; /* current processor priority */
int rtt = 0; /* rtt don't trap yet flag */
d_word oldpc;
static char buf[80];
/*
* Clear execution stop flag and install SIGINT handler.
*/
stop_it = 0;
signal( SIGINT, intr_hand );
Uint32 last_screen_update = SDL_GetTicks();
double timing_delta = ticks - SDL_GetTicks() * (TICK_RATE/1000.0);
c_addr startpc = p->regs[PC];
/*
* Run until told to stop.
*/
do
{
addtocybuf(p->regs[PC]);
/*
* Fetch and execute the instruction.
*/
if (traceflag) {
disas(p->regs[PC], buf);
if (tracefile) fprintf(tracefile, "%s\t%s\n", buf, state(p));
else printf("%s\n", buf);
}
result = ll_word( p, p->regs[PC], &p->ir );
oldpc = p->regs[PC];
p->regs[PC] += 2;
if (result == OK) {
result = (itab[p->ir>>6])( p );
timing(p);
}
LOAD_GAME();
/*
* Mop up the mess.
*/
if ( result != OK ) {
switch( result ) {
case BUS_ERROR: /* vector 4 */
ticks += 64;
case ODD_ADDRESS:
fprintf( stderr, _(" pc=%06o, last branch @ %06o\n"),
oldpc, last_branch );
result2 = service( (d_word) 04 );
break;
case CPU_ILLEGAL: /* vector 10 */
#undef VERBOSE_ILLEGAL
#ifdef VERBOSE_ILLEGAL
disas(oldpc, buf);
fprintf( stderr,
_("Illegal inst. %s, last branch @ %06o\n"),
buf, last_branch );
#endif
result2 = service( (d_word) 010 );
break;
case CPU_BPT: /* vector 14 */
result2 = service( (d_word) 014 );
break;
case CPU_EMT: /* vector 30 */
result2 = service( (d_word) 030 );
break;
case CPU_TRAP: /* vector 34 */
result2 = service( (d_word) 034 );
break;
case CPU_IOT: /* vector 20 */
result2 = service( (d_word) 020 );
break;
case CPU_WAIT:
in_wait_instr = 1;
result2 = OK;
break;
case CPU_RTT:
rtt = 1;
result2 = OK;
break;
case CPU_HALT:
io_stop_happened = 4;
result2 = service( (d_word) 004 );
break;
default:
fprintf( stderr, _("\nUnexpected return.\n") );
fprintf( stderr, _("exec=%d pc=%06o ir=%06o\n"),
result, oldpc, p->ir );
flag = 0;
result2 = OK;
break;
}
if ( result2 != OK ) {
fprintf( stderr, _("\nDouble trap @ %06o.\n"), oldpc);
lc_word(0177716, &p->regs[PC]);
p->regs[PC] &= 0177400;
/* p->regs[SP] = 01000; /* whatever */
}
}
if (( p->psw & 020) && (rtt == 0 )) { /* trace bit */
if ( service((d_word) 014 ) != OK ) {
fprintf( stderr, _("\nDouble trap @ %06o.\n"), p->regs[PC]);
lc_word(0177716, &p->regs[PC]);
p->regs[PC] &= 0177400;
p->regs[SP] = 01000; /* whatever */
}
}
rtt = 0;
p->total++;
if (nflag)
sound_flush();
if (bkmodel && ticks >= ticks_timer) {
scr_sync();
if (timer_intr_enabled) {
ev_register(TIMER_PRI, service, 0, 0100);
}
ticks_timer += half_frame_delay;
}
if (ticks >= ticks_screen) {
/* In full speed, update every 40 real ms */
if (fullspeed) {
Uint32 cur_sdl_ticks = SDL_GetTicks();
if (cur_sdl_ticks - last_screen_update >= 40) {
last_screen_update = cur_sdl_ticks;
scr_flush();
}
} else {
scr_flush();
}
tty_recv();
ticks_screen += frame_delay;
/* In simulated speed, if we're more than 10 ms
* ahead, slow down. Avoid rounding the delay up
* by SDL. If the sound is on, sound buffering
* provides synchronization.
*/
if (!fullspeed && !nflag) {
double cur_delta =
ticks - SDL_GetTicks() * (TICK_RATE/1000.0);
if (cur_delta - timing_delta > TICK_RATE/100) {
int msec = (cur_delta - timing_delta) / (TICK_RATE/1000);
SDL_Delay((msec / 10 * 10));
}
}
}
/*
* See if execution should be stopped. If so
* stop running, otherwise look for events
* to fire.
*/
if ( stop_it ) {
fprintf( stderr, _("\nExecution interrupted.\n") );
flag = 0;
} else {
priority = ( p->psw >> 5) & 7;
if ( pending_interrupts && priority != 7 ) {
ev_fire( priority );
}
}
if (checkpoint(p->regs[PC]) || hasexit == 1) {
flag = 0;
}
} while( flag );
signal( SIGINT, SIG_DFL );
}
/*
* intr_hand() - Handle SIGINT during execution by breaking
* back to user interface at the end of the current instruction.
......@@ -652,7 +110,7 @@ void intr_hand()
stop_it = 1;
}
static int checkpoint(d_word pc)
int checkpoint(d_word pc)
{
switch(pc) {
case 0116256:
......@@ -717,72 +175,6 @@ static int checkpoint(d_word pc)
return (pc == breakpoint);
}
showemuhelp()
{
fprintf(stderr, _("Emulator window hotkeys:\n\n"));
fprintf(stderr, _(" ScrollLock - Toggle video mode (B/W, Color)\n"));
fprintf(stderr, _(" Left Super+F11 - Reset emulated machine\n"));
fprintf(stderr, _(" F12 - Load a file into BK memory\n\n"));
}
showbkhelp()
{
char *monitor10help = _("BK0010 MONITOR (the OS) commands:\n\n\
'A' to 'K' - Quit MONITOR.\n\
'M' - Read from tape. Press 'Enter' and type in the filename of\n\
the desired .bin snapshot. Wait until the data loads into\n\