src/main.c

Thu, 02 Dec 2010 23:03:13 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Thu, 02 Dec 2010 23:03:13 +0000
changeset 40
239bc48590ba
parent 39
cab49f90c3b9
child 41
75887b42d7e5
permissions
-rw-r--r--

move memory access and mapping functions into memory.[ch]

This is to tidy up main.c...

philpem@0 1 #include <stdio.h>
philpem@7 2 #include <stdlib.h>
philpem@4 3 #include <stdint.h>
philpem@7 4 #include <stdbool.h>
philpem@7 5 #include <malloc.h>
philpem@7 6 #include <string.h>
philpem@18 7
philpem@20 8 #include "SDL.h"
philpem@20 9
philpem@4 10 #include "musashi/m68k.h"
philpem@7 11 #include "version.h"
philpem@18 12 #include "state.h"
philpem@40 13 #include "memory.h"
philpem@7 14
philpem@7 15 void FAIL(char *err)
philpem@7 16 {
philpem@7 17 state_done();
philpem@7 18 fprintf(stderr, "ERROR: %s\nExiting...\n", err);
philpem@7 19 exit(EXIT_FAILURE);
philpem@7 20 }
philpem@7 21
philpem@27 22 /****************************
philpem@27 23 * blessed be thy main()...
philpem@27 24 ****************************/
philpem@27 25
philpem@0 26 int main(void)
philpem@0 27 {
philpem@7 28 // copyright banner
philpem@16 29 printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator. Version %s, %s mode.\n", VER_FULLSTR, VER_BUILD_TYPE);
philpem@17 30 printf("Copyright (C) 2010 P. A. Pemberton. All rights reserved.\nLicensed under the Apache License Version 2.0.\n");
philpem@17 31 printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
philpem@16 32 printf("Built %s by %s@%s.\n", VER_COMPILE_DATETIME, VER_COMPILE_BY, VER_COMPILE_HOST);
philpem@16 33 printf("Compiler: %s\n", VER_COMPILER);
philpem@16 34 printf("CFLAGS: %s\n", VER_CFLAGS);
philpem@17 35 printf("\n");
philpem@7 36
philpem@7 37 // set up system state
philpem@7 38 // 512K of RAM
philpem@18 39 state_init(512*1024);
philpem@7 40
philpem@20 41 // set up musashi and reset the CPU
philpem@7 42 m68k_set_cpu_type(M68K_CPU_TYPE_68010);
philpem@7 43 m68k_pulse_reset();
philpem@9 44
philpem@28 45 // Set up SDL
philpem@20 46 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) {
philpem@20 47 printf("Could not initialise SDL: %s.\n", SDL_GetError());
philpem@28 48 exit(EXIT_FAILURE);
philpem@20 49 }
philpem@7 50
philpem@28 51 // Make sure SDL cleans up after itself
philpem@28 52 atexit(SDL_Quit);
philpem@28 53
philpem@28 54 // Set up the video display
philpem@28 55 SDL_Surface *screen = NULL;
philpem@28 56 if ((screen = SDL_SetVideoMode(720, 384, 8, SDL_SWSURFACE | SDL_ANYFORMAT)) == NULL) {
philpem@28 57 printf("Could not find a suitable video mode: %s.\n", SDL_GetError());
philpem@28 58 exit(EXIT_FAILURE);
philpem@28 59 }
philpem@32 60 printf("Set %dx%d at %d bits-per-pixel mode\n\n", screen->w, screen->h, screen->format->BitsPerPixel);
philpem@28 61 SDL_WM_SetCaption("FreeBee 3B1 emulator", "FreeBee");
philpem@28 62
philpem@20 63 /***
philpem@20 64 * The 3B1 CPU runs at 10MHz, with DMA running at 1MHz and video refreshing at
philpem@20 65 * around 60Hz (???), with a 60Hz periodic interrupt.
philpem@20 66 */
philpem@20 67 const uint32_t TIMESLOT_FREQUENCY = 240; // Hz
philpem@20 68 const uint32_t MILLISECS_PER_TIMESLOT = 1e3 / TIMESLOT_FREQUENCY;
philpem@20 69 const uint32_t CLOCKS_PER_60HZ = (10e6 / 60);
philpem@20 70 uint32_t next_timeslot = SDL_GetTicks() + MILLISECS_PER_TIMESLOT;
philpem@20 71 uint32_t clock_cycles = 0;
philpem@16 72 bool exitEmu = false;
philpem@16 73 for (;;) {
philpem@20 74 // Run the CPU for however many cycles we need to. CPU core clock is
philpem@20 75 // 10MHz, and we're running at 240Hz/timeslot. Thus: 10e6/240 or
philpem@20 76 // 41667 cycles per timeslot.
philpem@20 77 clock_cycles += m68k_execute(10e6/TIMESLOT_FREQUENCY);
philpem@20 78
philpem@20 79 // TODO: run DMA here
philpem@16 80
philpem@20 81 // Is it time to run the 60Hz periodic interrupt yet?
philpem@20 82 if (clock_cycles > CLOCKS_PER_60HZ) {
philpem@20 83 // TODO: refresh screen
philpem@20 84 // TODO: trigger periodic interrupt (if enabled)
philpem@20 85 // decrement clock cycle counter, we've handled the intr.
philpem@20 86 clock_cycles -= CLOCKS_PER_60HZ;
philpem@16 87 }
philpem@16 88
philpem@20 89 // make sure frame rate is equal to real time
philpem@20 90 uint32_t now = SDL_GetTicks();
philpem@20 91 if (now < next_timeslot) {
philpem@20 92 // timeslot finished early -- eat up some time
philpem@20 93 SDL_Delay(next_timeslot - now);
philpem@20 94 } else {
philpem@20 95 // timeslot finished late -- skip ahead to gain time
philpem@20 96 // TODO: if this happens a lot, we should let the user know
philpem@20 97 // that their PC might not be fast enough...
philpem@20 98 next_timeslot = now;
philpem@20 99 }
philpem@20 100 // advance to the next timeslot
philpem@20 101 next_timeslot += MILLISECS_PER_TIMESLOT;
philpem@20 102
philpem@20 103 // if we've been asked to exit the emulator, then do so.
philpem@16 104 if (exitEmu) break;
philpem@16 105 }
philpem@7 106
philpem@7 107 // shut down and exit
philpem@20 108 SDL_Quit();
philpem@7 109
philpem@0 110 return 0;
philpem@0 111 }