Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Libretro
bk-emulator
Commits
8c226e88
Commit
8c226e88
authored
Nov 01, 2019
by
Vladimir Serbinenko
Browse files
Move main loop to a separate file
parent
d75aeb21
Changes
4
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
8c226e88
...
...
@@ -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
...
...
defines.h
View file @
8c226e88
...
...
@@ -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
main.c
View file @
8c226e88
...
...
@@ -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
,
_
(
"
\n
Examples:.
\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
,
_
(
"
\n
Unexpected 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
,
_
(
"
\n
Double 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
,
_
(
"
\n
Double 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
,
_
(
"
\n
Execution 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
\