src/main.c

Sun, 28 Nov 2010 20:02:45 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 28 Nov 2010 20:02:45 +0000
changeset 8
e2dcbabc7e1c
parent 7
7b98c7665aae
child 9
3e99497dca33
permissions
-rw-r--r--

remove debug fluff

     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 	// free the data arrays and close the files
    86 	free(romdat1);
    87 	free(romdat2);
    88 	fclose(r14c);
    89 	fclose(r15c);
    91 	return 0;
    92 }
    94 void state_done()
    95 {
    96 	if (state.ram != NULL)
    97 		free(state.ram);
    98 }
   100 // read m68k memory
   101 // TODO: refactor musashi to use stdint, and properly sized integers!
   102 // TODO: find a way to make musashi use function pointers instead of hard coded callbacks, maybe use a context struct too
   103 uint32_t m68k_read_memory_32(uint32_t address)
   104 {
   105 	// If ROMLMAP is set, force system to access ROM
   106 	if (!state.romlmap)
   107 		address |= 0x800000;
   109 	if (address >= 0xC00000) {
   110 		// I/O Registers B
   111 		// TODO
   112 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   113 		// ROM access
   114 		return state.rom[(address & (ROM_SIZE-1)) / 4];
   115 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   116 		// I/O Registers A
   117 		// TODO
   118 	} else if (address <= 0x3FFFFF) {
   119 		// RAM
   120 		return state.ram[(address & state.ram_addr_mask) / 4];
   121 	}
   122 	return 0xffffffff;
   123 }
   125 uint32_t m68k_read_memory_16(uint32_t address)
   126 {
   127 	if (address & 2) {
   128 		return m68k_read_memory_32(address) & 0xFFFF;
   129 	} else {
   130 		return (m68k_read_memory_32(address) >> 16) & 0xFFFF;
   131 	}
   132 }
   134 uint32_t m68k_read_memory_8(uint32_t address)
   135 {
   136 	// If ROMLMAP is set, force system to access ROM
   137 	if (!state.romlmap)
   138 		address |= 0x800000;
   140 	switch (address & 3) {
   141 		case 3:		return m68k_read_memory_32(address)			& 0xFF;
   142 		case 2:		return (m68k_read_memory_32(address) >> 8)	& 0xFF;
   143 		case 1:		return (m68k_read_memory_32(address) >> 16)	& 0xFF;
   144 		case 0:		return (m68k_read_memory_32(address) >> 24)	& 0xFF;
   145 	}
   146 	return 0xffffffff;
   147 }
   149 // write m68k memory
   150 void m68k_write_memory_32(uint32_t address, uint32_t value)
   151 {
   152 	// If ROMLMAP is set, force system to access ROM
   153 	if (!state.romlmap)
   154 		address |= 0x800000;
   156 	if (address >= 0xC00000) {
   157 		// I/O Registers B
   158 		// TODO
   159 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   160 		// ROM access
   161 		// TODO: bus error here? can't write to rom!
   162 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   163 		// I/O Registers A
   164 		// TODO
   165 	} else if (address <= 0x3FFFFF) {
   166 		// RAM
   167 		state.ram[(address & state.ram_addr_mask) / 4] = value;
   168 	}
   169 }
   171 void m68k_write_memory_16(uint32_t address, uint32_t value)
   172 {
   173 	// If ROMLMAP is set, force system to access ROM
   174 	if (!state.romlmap)
   175 		address |= 0x800000;
   177 	if (address >= 0xC00000) {
   178 		// I/O Registers B
   179 		// TODO
   180 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   181 		// ROM access
   182 		// TODO: bus error here? can't write to rom!
   183 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   184 		// I/O Registers A
   185 		// TODO
   186 	} else if (address <= 0x3FFFFF) {
   187 		// RAM
   188 		if (address & 2)
   189 			state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFF0000) | (value & 0xFFFF);
   190 		else
   191 			state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0x0000FFFF) | ((value & 0xFFFF) << 16);
   192 	}
   193 }
   195 void m68k_write_memory_8(uint32_t address, uint32_t value)
   196 {
   197 	// If ROMLMAP is set, force system to access ROM
   198 	if (!state.romlmap)
   199 		address |= 0x800000;
   201 	if (address >= 0xC00000) {
   202 		// I/O Registers B
   203 		// TODO
   204 	} else if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   205 		// ROM access
   206 		// TODO: bus error here? can't write to rom!
   207 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   208 		// I/O Registers A
   209 		// TODO
   210 	} else if (address <= 0x3FFFFF) {
   211 		// RAM
   212 		switch (address & 3) {
   213 			case 3:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFFFF00) | (value & 0xFF);
   214 			case 2:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFF00FF) | ((value & 0xFF) << 8);
   215 			case 1:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFF00FFFF) | ((value & 0xFF) << 16);
   216 			case 0:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0x00FFFFFF) | ((value & 0xFF) << 24);
   217 		}
   218 	}
   219 }
   221 int main(void)
   222 {
   223 	// copyright banner
   224 	printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator\n");
   225 	printf("Copyright (C) 2010 P. A. Pemberton.\n");
   226 	printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
   228 	// set up system state
   229 	// 512K of RAM
   230 	state.ram_size = 512*1024;
   231 	state_init();
   233 	// set up musashi
   234 	m68k_set_cpu_type(M68K_CPU_TYPE_68010);
   235 	m68k_pulse_reset();
   237 	// set up SDL
   239 	// emulation loop!
   240 	// repeat:
   241 	// 		m68k_execute()
   242 	// 		m68k_set_irq() every 60ms
   243 	printf("ran for %d cycles\n", m68k_execute(100000));
   245 	// shut down and exit
   247 	return 0;
   248 }