aboutsummaryrefslogtreecommitdiff
path: root/src/fake86/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fake86/main.c')
-rwxr-xr-xsrc/fake86/main.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/src/fake86/main.c b/src/fake86/main.c
new file mode 100755
index 0000000..78b3c43
--- /dev/null
+++ b/src/fake86/main.c
@@ -0,0 +1,321 @@
+/*
+ Fake86: A portable, open-source 8086 PC emulator.
+ Copyright (C)2010-2013 Mike Chambers
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* main.c: functions to initialize the different components of Fake86,
+ load ROM binaries, and kickstart the CPU emulator. */
+
+#include "config.h"
+#ifdef __APPLE__ /* Memory leaks occur in OS X when the SDL window gets */
+#include <SDL/SDL.h> /* resized if SDL.h not included in file with main() */
+#endif
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include "mutex.h"
+#ifdef _WIN32
+CRITICAL_SECTION screenmutex;
+#else
+#ifndef __APPLE__
+#include <X11/Xlib.h>
+#endif
+pthread_t consolethread;
+#endif
+
+const uint8_t *build = BUILD_STRING;
+
+extern uint8_t RAM[0x100000], readonly[0x100000];
+extern uint8_t running, renderbenchmark;
+
+extern void reset86();
+extern void exec86 (uint32_t execloops);
+extern uint8_t initscreen (uint8_t *ver);
+extern void VideoThread();
+extern doscrmodechange();
+extern void handleinput();
+
+#ifdef CPU_ADDR_MODE_CACHE
+extern uint64_t cached_access_count, uncached_access_count;
+#endif
+
+extern uint8_t scrmodechange, doaudio;
+extern uint64_t totalexec, totalframes;
+uint64_t starttick, endtick, lasttick;
+
+uint8_t *biosfile = NULL, verbose = 0, cgaonly = 0, useconsole = 0;
+uint32_t speed = 0;
+
+
+uint32_t loadbinary (uint32_t addr32, uint8_t *filename, uint8_t roflag) {
+ FILE *binfile = NULL;
+ uint32_t readsize;
+
+ binfile = fopen (filename, "rb");
+ if (binfile == NULL) {
+ return (0);
+ }
+
+ fseek (binfile, 0, SEEK_END);
+ readsize = ftell (binfile);
+ fseek (binfile, 0, SEEK_SET);
+ fread ( (void *) &RAM[addr32], 1, readsize, binfile);
+ fclose (binfile);
+
+ memset ( (void *) &readonly[addr32], roflag, readsize);
+ return (readsize);
+}
+
+uint32_t loadrom (uint32_t addr32, uint8_t *filename, uint8_t failure_fatal) {
+ uint32_t readsize;
+ readsize = loadbinary (addr32, filename, 1);
+ if (!readsize) {
+ if (failure_fatal) printf("FATAL: ");
+ else printf("WARNING: ");
+ printf ("Unable to load %s\n", filename);
+ return (0);
+ }
+ else {
+ printf ("Loaded %s at 0x%05X (%lu KB)\n", filename, addr32, readsize >> 10);
+ return (readsize);
+ }
+}
+
+uint32_t loadbios (uint8_t *filename) {
+ FILE *binfile = NULL;
+ uint32_t readsize;
+
+ binfile = fopen (filename, "rb");
+ if (binfile == NULL) {
+ return (0);
+ }
+
+ fseek (binfile, 0, SEEK_END);
+ readsize = ftell (binfile);
+ fseek (binfile, 0, SEEK_SET);
+ fread ( (void *) &RAM[0x100000 - readsize], 1, readsize, binfile);
+ fclose (binfile);
+
+ memset ( (void *) &readonly[0x100000 - readsize], 1, readsize);
+ return (readsize);
+}
+
+extern uint32_t SDL_GetTicks();
+extern uint8_t insertdisk (uint8_t drivenum, char *filename);
+extern void ejectdisk (uint8_t drivenum);
+extern uint8_t bootdrive, ethif, net_enabled;
+extern void doirq (uint8_t irqnum);
+//extern void isa_ne2000_init(int baseport, uint8_t irq);
+extern void parsecl (int argc, char *argv[]);
+void timing();
+void tickaudio();
+void inittiming();
+void initaudio();
+void init8253();
+void init8259();
+extern void init8237();
+extern void initVideoPorts();
+extern void killaudio();
+extern void initsermouse (uint16_t baseport, uint8_t irq);
+extern void *port_write_callback[0x10000];
+extern void *port_read_callback[0x10000];
+extern void *port_write_callback16[0x10000];
+extern void *port_read_callback16[0x10000];
+extern void initadlib (uint16_t baseport);
+extern void initsoundsource();
+extern void isa_ne2000_init (uint16_t baseport, uint8_t irq);
+extern void initBlaster (uint16_t baseport, uint8_t irq);
+
+#ifdef NETWORKING_ENABLED
+extern void initpcap();
+extern void dispatch();
+#endif
+
+void printbinary (uint8_t value) {
+ int8_t curbit;
+
+ for (curbit=7; curbit>=0; curbit--) {
+ if ( (value >> curbit) & 1) printf ("1");
+ else printf ("0");
+ }
+}
+
+uint8_t usessource = 0;
+void inithardware() {
+#ifdef NETWORKING_ENABLED
+ if (ethif != 254) initpcap();
+#endif
+ printf ("Initializing emulated hardware:\n");
+ memset (port_write_callback, 0, sizeof (port_write_callback) );
+ memset (port_read_callback, 0, sizeof (port_read_callback) );
+ memset (port_write_callback16, 0, sizeof (port_write_callback16) );
+ memset (port_read_callback16, 0, sizeof (port_read_callback16) );
+ printf (" - Intel 8253 timer: ");
+ init8253();
+ printf ("OK\n");
+ printf (" - Intel 8259 interrupt controller: ");
+ init8259();
+ printf ("OK\n");
+ printf (" - Intel 8237 DMA controller: ");
+ init8237();
+ printf ("OK\n");
+ initVideoPorts();
+ if (usessource) {
+ printf (" - Disney Sound Source: ");
+ initsoundsource();
+ printf ("OK\n");
+ }
+#ifndef NETWORKING_OLDCARD
+ printf (" - Novell NE2000 ethernet adapter: ");
+ isa_ne2000_init (0x300, 6);
+ printf ("OK\n");
+#endif
+ printf (" - Adlib FM music card: ");
+ initadlib (0x388);
+ printf ("OK\n");
+ printf (" - Creative Labs Sound Blaster 2.0: ");
+ initBlaster (0x220, 7);
+ printf ("OK\n");
+ printf (" - Serial mouse (Microsoft compatible): ");
+ initsermouse (0x3F8, 4);
+ printf ("OK\n");
+ if (doaudio) initaudio();
+ inittiming();
+ initscreen ( (uint8_t *) build);
+}
+
+uint8_t dohardreset = 0;
+uint8_t audiobufferfilled();
+
+#ifdef _WIN32
+void initmenus();
+void EmuThread (void *dummy) {
+#else
+pthread_t emuthread;
+void *EmuThread (void *dummy) {
+#endif
+ while (running) {
+ if (!speed) exec86 (10000);
+ else {
+ exec86(speed / 100);
+ while (!audiobufferfilled()) {
+ timing();
+ tickaudio();
+ }
+#ifdef _WIN32
+ Sleep(10);
+#else
+ usleep(10000);
+#endif
+ }
+ if (scrmodechange) doscrmodechange();
+ if (dohardreset) {
+ reset86();
+ dohardreset = 0;
+ }
+ }
+}
+
+#ifdef _WIN32
+void runconsole (void *dummy);
+#else
+void *runconsole (void *dummy);
+#endif
+extern void bufsermousedata (uint8_t value);
+int main (int argc, char *argv[]) {
+ uint32_t biossize;
+
+ printf ("%s (c)2010-2013 Mike Chambers\n", build);
+ printf ("[A portable, open-source 8086 PC emulator]\n\n");
+
+ parsecl (argc, argv);
+
+ memset (readonly, 0, 0x100000);
+ biossize = loadbios (biosfile);
+ if (!biossize) return (-1);
+#ifdef DISK_CONTROLLER_ATA
+ if (!loadrom (0xD0000UL, PATH_DATAFILES "ide_xt.bin", 1) ) return (-1);
+#endif
+ if (biossize <= 8192) {
+ loadrom (0xF6000UL, PATH_DATAFILES "rombasic.bin", 0);
+ if (!loadrom (0xC0000UL, PATH_DATAFILES "videorom.bin", 1) ) return (-1);
+ }
+ printf ("\nInitializing CPU... ");
+ running = 1;
+ reset86();
+ printf ("OK!\n");
+
+#ifndef _WIN32
+#ifndef __APPLE__
+ XInitThreads();
+#endif
+#endif
+ inithardware();
+
+#ifdef _WIN32
+ initmenus();
+ InitializeCriticalSection (&screenmutex);
+#endif
+ if (useconsole) {
+#ifdef _WIN32
+ _beginthread (runconsole, 0, NULL);
+#else
+ pthread_create (&consolethread, NULL, (void *) runconsole, NULL);
+#endif
+ }
+
+#ifdef _WIN32
+ _beginthread (EmuThread, 0, NULL);
+#else
+ pthread_create (&emuthread, NULL, (void *) EmuThread, NULL);
+#endif
+
+ lasttick = starttick = SDL_GetTicks();
+ while (running) {
+ handleinput();
+#ifdef NETWORKING_ENABLED
+ if (ethif < 254) dispatch();
+#endif
+#ifdef _WIN32
+ Sleep(1);
+#else
+ usleep(1000);
+#endif
+ }
+ endtick = (SDL_GetTicks() - starttick) / 1000;
+ if (endtick == 0) endtick = 1; //avoid divide-by-zero exception in the code below, if ran for less than 1 second
+
+ killaudio();
+
+ if (renderbenchmark) {
+ printf ("\n%llu frames rendered in %llu seconds.\n", totalframes, endtick);
+ printf ("Average framerate: %llu FPS.\n", totalframes / endtick);
+ }
+
+ printf ("\n%llu instructions executed in %llu seconds.\n", totalexec, endtick);
+ printf ("Average speed: %llu instructions/second.\n", totalexec / endtick);
+
+#ifdef CPU_ADDR_MODE_CACHE
+ printf ("\n Cached modregrm data access count: %llu\n", cached_access_count);
+ printf ("Uncached modregrm data access count: %llu\n", uncached_access_count);
+#endif
+
+ if (useconsole) exit (0); //makes sure console thread quits even if blocking
+
+ return (0);
+}