src/main.c

Sun, 28 Nov 2010 19:53:53 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 28 Nov 2010 19:53:53 +0000
changeset 7
7b98c7665aae
parent 4
21a7b07b6310
child 8
e2dcbabc7e1c
permissions
-rw-r--r--

set up ROM loader and state storage, add basic emulator core

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <stdint.h>
     4 #include <stdbool.h>
     5 #include <malloc.h>
     6 #include <string.h>
     7 #include "musashi/m68k.h"
     8 #include "version.h"
    10 #define ROM_SIZE (32768/4)
    12 void state_done(void);
    14 void FAIL(char *err)
    15 {
    16 	state_done();
    17 	fprintf(stderr, "ERROR: %s\nExiting...\n", err);
    18 	exit(EXIT_FAILURE);
    19 }
    22 struct {
    23 	// Boot PROM can be up to 32Kbytes total size
    24 	uint32_t	rom[ROM_SIZE];
    26 	// Main system RAM
    27 	uint32_t	*ram;
    28 	size_t		ram_size;			// number of RAM bytes allocated
    29 	uint32_t	ram_addr_mask;		// address mask
    31 	// GENERAL CONTROL REGISTER
    32 	bool		romlmap;
    33 } state;
    35 int state_init()
    36 {
    37 	// Free RAM if it's allocated
    38 	if (state.ram != NULL)
    39 		free(state.ram);
    41 	// Initialise hardware registers
    42 	state.romlmap = false;
    44 	// Allocate RAM
    45 	// TODO: make sure ram size selection is valid!
    46 	state.ram = malloc(state.ram_size);
    47 	if (state.ram == NULL)
    48 		return -1;
    49 	state.ram_addr_mask = state.ram_size - 1;
    51 	// Load ROMs
    52 	FILE *r14c, *r15c;
    53 	r14c = fopen("roms/14c.bin", "rb");
    54 	if (r14c == NULL) FAIL("unable to open roms/14c.bin");
    55 	r15c = fopen("roms/15c.bin", "rb");
    56 	if (r15c == NULL) FAIL("unable to open roms/15c.bin");
    58 	// get ROM file size
    59 	fseek(r14c, 0, SEEK_END);
    60 	size_t romlen = ftell(r14c);
    61 	fseek(r14c, 0, SEEK_SET);
    62 	fseek(r15c, 0, SEEK_END);
    63 	size_t romlen2 = ftell(r15c);
    64 	fseek(r15c, 0, SEEK_SET);
    65 	if (romlen2 != romlen) FAIL("ROMs are not the same size!");
    66 	if ((romlen / 4) > (ROM_SIZE / 2)) FAIL("ROM 14C is too big!");
    67 	if ((romlen2 / 4) > (ROM_SIZE / 2)) FAIL("ROM 15C is too big!");
    69 	// sanity checks completed; load the ROMs!
    70 	uint8_t *romdat1, *romdat2;
    71 	romdat1 = malloc(romlen);
    72 	romdat2 = malloc(romlen2);
    73 	fread(romdat1, 1, romlen, r15c);
    74 	fread(romdat2, 1, romlen2, r14c);
    76 	// convert the ROM data
    77 	for (size_t i=0; i<romlen; i+=2) {
    78 		state.rom[i/2] = (
    79 				(romdat1[i+0] << 24) |
    80 				(romdat2[i+0] << 16) |
    81 				(romdat1[i+1] << 8)  |
    82 				(romdat2[i+1]));
    83 	}
    85 	for (int i=0; i<8; i++)
    86 		printf("%02X %02X ", romdat1[i], romdat2[i]);
    87 	printf("\n%08X %08X\n", state.rom[0], state.rom[1]);
    89 	// free the data arrays and close the files
    90 	free(romdat1);
    91 	free(romdat2);
    92 	fclose(r14c);
    93 	fclose(r15c);
    95 	return 0;
    96 }
    98 void state_done()
    99 {
   100 	if (state.ram != NULL)
   101 		free(state.ram);
   102 }
   104 // read m68k memory
   105 // TODO: refactor musashi to use stdint, and properly sized integers!
   106 // TODO: find a way to make musashi use function pointers instead of hard coded callbacks, maybe use a context struct too
   107 uint32_t m68k_read_memory_32(uint32_t address)
   108 {
   109 	// If ROMLMAP is set, force system to access ROM
   110 	if (!state.romlmap)
   111 		address |= 0x800000;
   113 	if (address >= 0xC00000) {
   114 		// I/O Registers B
   115 		// TODO
   116 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   117 		// ROM access
   118 		printf("%08X\n", state.rom[(address & (ROM_SIZE-1)) / 4]);
   119 		return state.rom[(address & (ROM_SIZE-1)) / 4];
   120 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   121 		// I/O Registers A
   122 		// TODO
   123 	} else if (address <= 0x3FFFFF) {
   124 		// RAM
   125 		return state.ram[(address & state.ram_addr_mask) / 4];
   126 	}
   127 	return 0xffffffff;
   128 }
   130 uint32_t m68k_read_memory_16(uint32_t address)
   131 {
   132 	if (address & 2) {
   133 		return m68k_read_memory_32(address) & 0xFFFF;
   134 	} else {
   135 		return (m68k_read_memory_32(address) >> 16) & 0xFFFF;
   136 	}
   137 }
   139 uint32_t m68k_read_memory_8(uint32_t address)
   140 {
   141 	// If ROMLMAP is set, force system to access ROM
   142 	if (!state.romlmap)
   143 		address |= 0x800000;
   145 	switch (address & 3) {
   146 		case 3:		return m68k_read_memory_32(address)			& 0xFF;
   147 		case 2:		return (m68k_read_memory_32(address) >> 8)	& 0xFF;
   148 		case 1:		return (m68k_read_memory_32(address) >> 16)	& 0xFF;
   149 		case 0:		return (m68k_read_memory_32(address) >> 24)	& 0xFF;
   150 	}
   151 	return 0xffffffff;
   152 }
   154 // write m68k memory
   155 void m68k_write_memory_32(uint32_t address, uint32_t value)
   156 {
   157 	// If ROMLMAP is set, force system to access ROM
   158 	if (!state.romlmap)
   159 		address |= 0x800000;
   161 	if (address >= 0xC00000) {
   162 		// I/O Registers B
   163 		// TODO
   164 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   165 		// ROM access
   166 		// TODO: bus error here? can't write to rom!
   167 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   168 		// I/O Registers A
   169 		// TODO
   170 	} else if (address <= 0x3FFFFF) {
   171 		// RAM
   172 		state.ram[(address & state.ram_addr_mask) / 4] = value;
   173 	}
   174 }
   176 void m68k_write_memory_16(uint32_t address, uint32_t value)
   177 {
   178 	// If ROMLMAP is set, force system to access ROM
   179 	if (!state.romlmap)
   180 		address |= 0x800000;
   182 	if (address >= 0xC00000) {
   183 		// I/O Registers B
   184 		// TODO
   185 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   186 		// ROM access
   187 		// TODO: bus error here? can't write to rom!
   188 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   189 		// I/O Registers A
   190 		// TODO
   191 	} else if (address <= 0x3FFFFF) {
   192 		// RAM
   193 		if (address & 2)
   194 			state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFF0000) | (value & 0xFFFF);
   195 		else
   196 			state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0x0000FFFF) | ((value & 0xFFFF) << 16);
   197 	}
   198 }
   200 void m68k_write_memory_8(uint32_t address, uint32_t value)
   201 {
   202 	// If ROMLMAP is set, force system to access ROM
   203 	if (!state.romlmap)
   204 		address |= 0x800000;
   206 	if (address >= 0xC00000) {
   207 		// I/O Registers B
   208 		// TODO
   209 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   210 		// ROM access
   211 		// TODO: bus error here? can't write to rom!
   212 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   213 		// I/O Registers A
   214 		// TODO
   215 	} else if (address <= 0x3FFFFF) {
   216 		// RAM
   217 		switch (address & 3) {
   218 			case 3:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFFFF00) | (value & 0xFF);
   219 			case 2:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFF00FF) | ((value & 0xFF) << 8);
   220 			case 1:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFF00FFFF) | ((value & 0xFF) << 16);
   221 			case 0:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0x00FFFFFF) | ((value & 0xFF) << 24);
   222 		}
   223 	}
   224 }
   226 int main(void)
   227 {
   228 	// copyright banner
   229 	printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator\n");
   230 	printf("Copyright (C) 2010 P. A. Pemberton.\n");
   231 	printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
   233 	// set up system state
   234 	// 512K of RAM
   235 	state.ram_size = 512*1024;
   236 	state_init();
   238 	// set up musashi
   239 	m68k_set_cpu_type(M68K_CPU_TYPE_68010);
   240 	m68k_pulse_reset();
   242 	// set up SDL
   244 	// emulation loop!
   245 	// repeat:
   246 	// 		m68k_execute()
   247 	// 		m68k_set_irq() every 60ms
   248 	m68k_execute(100000);
   250 	// shut down and exit
   252 	return 0;
   253 }