src/main.c

Sun, 28 Nov 2010 20:52:53 +0000

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

fix memory read stuff, now need to deal with memory write

     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/2)
    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 	uint16_t	rom[ROM_SIZE];
    26 	// Main system RAM
    27 	uint16_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++) {
    78 		state.rom[i] = ((romdat1[i] << 8) | (romdat2[i]));
    79 	}
    81 	// free the data arrays and close the files
    82 	free(romdat1);
    83 	free(romdat2);
    84 	fclose(r14c);
    85 	fclose(r15c);
    87 	return 0;
    88 }
    90 void state_done()
    91 {
    92 	if (state.ram != NULL)
    93 		free(state.ram);
    94 }
    96 // read m68k memory
    97 // TODO: refactor musashi to use stdint, and properly sized integers!
    98 // TODO: find a way to make musashi use function pointers instead of hard coded callbacks, maybe use a context struct too
    99 uint32_t m68k_read_memory_32(uint32_t address)
   100 {
   101 	uint32_t data = 0xFFFFFFFF;
   103 	printf("RD32 %08X %d", address, state.romlmap);
   105 	// If ROMLMAP is set, force system to access ROM
   106 	if (!state.romlmap)
   107 		address |= 0x800000;
   109 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   110 		// ROM access
   111 		data = ((state.rom[(address & (ROM_SIZE-1)) / 2] << 16) | (state.rom[((address & (ROM_SIZE-1)) / 2)+1]));
   112 	} else if (address <= 0x3FFFFF) {
   113 		// RAM
   114 		data = state.ram[(address & state.ram_addr_mask) / 2];
   115 	}
   117 	printf(" ==> %04X\n", data);
   118 	return data;
   119 }
   121 uint32_t m68k_read_memory_16(uint32_t address)
   122 {
   123 	uint16_t data = 0xFFFF;
   125 	printf("RD16 %08X %d", address, state.romlmap);
   127 	// If ROMLMAP is set, force system to access ROM
   128 	if (!state.romlmap)
   129 		address |= 0x800000;
   131 	data = (m68k_read_memory_32(address) >> 16) & 0xFFFF;
   133 	printf(" ==> %04X\n", data);
   134 	return data;
   135 }
   137 uint32_t m68k_read_memory_8(uint32_t address)
   138 {
   139 	uint8_t data = 0xFF;
   141 	printf("RD 8 %08X %d ", address, state.romlmap);
   143 	// If ROMLMAP is set, force system to access ROM
   144 	if (!state.romlmap)
   145 		address |= 0x800000;
   147 	data = m68k_read_memory_32(address) & 0xFF;
   149 	printf("==> %02X\n", data);
   150 	return data;
   151 }
   153 // write m68k memory
   154 void m68k_write_memory_32(uint32_t address, uint32_t value)
   155 {
   156 	// If ROMLMAP is set, force system to access ROM
   157 	if (!state.romlmap)
   158 		address |= 0x800000;
   160 	printf("WR32 %08X %d %02X\n", address, state.romlmap, value);
   162 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   163 		// ROM access
   164 		// TODO: bus error here? can't write to rom!
   165 	} else if (address <= 0x3FFFFF) {
   166 		// RAM
   167 		state.ram[(address & state.ram_addr_mask) / 2] = (value >> 16);
   168 		state.ram[((address & state.ram_addr_mask) / 2)+1] = value & 0xffff;
   169 	} else {
   170 		switch (address) {
   171 			case 0xE43000:	state.romlmap = ((value & 0x8000) == 0x8000);
   172 		}
   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 	printf("WR16 %08X %d %02X\n", address, state.romlmap, value);
   184 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   185 		// ROM access
   186 		// TODO: bus error here? can't write to rom!
   187 	} else if (address <= 0x3FFFFF) {
   188 		// RAM
   189 		state.ram[(address & state.ram_addr_mask) / 2] = value & 0xFFFF;
   190 	} else {
   191 		switch (address) {
   192 			case 0xE43000:	state.romlmap = ((value & 0x8000) == 0x8000);
   193 		}
   194 	}
   195 }
   197 void m68k_write_memory_8(uint32_t address, uint32_t value)
   198 {
   199 	// If ROMLMAP is set, force system to access ROM
   200 	if (!state.romlmap)
   201 		address |= 0x800000;
   203 	printf("WR 8 %08X %d %02X\n", address, state.romlmap, value);
   205 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   206 		// ROM access
   207 		// TODO: bus error here? can't write to rom!
   208 	} else if (address <= 0x3FFFFF) {
   209 		// RAM
   210 		switch (address & 3) {
   211 			// FIXME
   212 			case 3:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFFFF00) | (value & 0xFF);
   213 			case 2:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFF00FF) | ((value & 0xFF) << 8);
   214 			case 1:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFF00FFFF) | ((value & 0xFF) << 16);
   215 			case 0:		state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0x00FFFFFF) | ((value & 0xFF) << 24);
   216 		}
   217 	} else {
   218 		switch (address) {
   219 			case 0xE43000:	state.romlmap = ((value & 0x80) == 0x80);
   220 		}
   221 	}
   222 }
   224 uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); }
   225 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); }
   226 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); }
   228 int main(void)
   229 {
   230 	// copyright banner
   231 	printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator\n");
   232 	printf("Copyright (C) 2010 P. A. Pemberton.\n");
   233 	printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
   235 	// set up system state
   236 	// 512K of RAM
   237 	state.ram_size = 512*1024;
   238 	state_init();
   240 	// set up musashi
   241 	m68k_set_cpu_type(M68K_CPU_TYPE_68010);
   242 	m68k_pulse_reset();
   244 	char dasm[512];
   245 	m68k_disassemble(dasm, 0x80001a, M68K_CPU_TYPE_68010);
   246 	printf("%s\n", dasm);
   248 	// set up SDL
   250 	// emulation loop!
   251 	// repeat:
   252 	// 		m68k_execute()
   253 	// 		m68k_set_irq() every 60ms
   254 	printf("ran for %d cycles\n", m68k_execute(100000));
   256 	// shut down and exit
   258 	return 0;
   259 }