src/main.c

Sun, 28 Nov 2010 22:04:14 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 28 Nov 2010 22:04:14 +0000
changeset 11
67bf6abb6e79
parent 10
dbf4ba9563c9
child 12
0c5bddf0289e
permissions
-rw-r--r--

enforce RAM size requirements

     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 void state_done(void);
    12 void FAIL(char *err)
    13 {
    14 	state_done();
    15 	fprintf(stderr, "ERROR: %s\nExiting...\n", err);
    16 	exit(EXIT_FAILURE);
    17 }
    19 // Maximum size of the Boot PROMs. Must be a binary power of two.
    20 #define ROM_SIZE 32768
    22 struct {
    23 	// Boot PROM can be up to 32Kbytes total size
    24 	uint8_t		rom[ROM_SIZE];
    26 	// Main system RAM
    27 	uint8_t		*ram;
    28 	size_t		ram_size;			// number of RAM bytes allocated
    30 	// GENERAL CONTROL REGISTER
    31 	bool		romlmap;
    32 } state;
    34 int state_init()
    35 {
    36 	// Free RAM if it's allocated
    37 	if (state.ram != NULL)
    38 		free(state.ram);
    40 	// Initialise hardware registers
    41 	state.romlmap = false;
    43 	// Allocate RAM, making sure the user has specified a valid RAM amount first
    44 	// Basically: 512KiB minimum, 4MiB maximum, in increments of 512KiB.
    45 	if ((state.ram_size < 512*1024) || ((state.ram_size % (512*1024)) != 0))
    46 		return -1;
    47 	state.ram = malloc(state.ram_size);
    48 	if (state.ram == NULL)
    49 		return -2;
    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 + romlen2) > ROM_SIZE) FAIL("ROMs are too large to fit in memory!");
    68 	// sanity checks completed; load the ROMs!
    69 	uint8_t *romdat1, *romdat2;
    70 	romdat1 = malloc(romlen);
    71 	romdat2 = malloc(romlen2);
    72 	fread(romdat1, 1, romlen, r15c);
    73 	fread(romdat2, 1, romlen2, r14c);
    75 	// convert the ROM data
    76 	for (size_t i=0; i<(romlen + romlen2); i+=2) {
    77 		state.rom[i+0] = romdat1[i/2];
    78 		state.rom[i+1] = romdat2[i/2];
    79 	}
    81 	for (size_t i=0; i<16; i++) printf("%02X ", state.rom[i]);
    82 	printf("\n");
    84 	// TODO: if ROM buffer not filled, repeat the ROM data we read until it is.
    86 	// free the data arrays and close the files
    87 	free(romdat1);
    88 	free(romdat2);
    89 	fclose(r14c);
    90 	fclose(r15c);
    92 	return 0;
    93 }
    95 void state_done()
    96 {
    97 	if (state.ram != NULL)
    98 		free(state.ram);
    99 }
   101 // read m68k memory
   102 uint32_t m68k_read_memory_32(uint32_t address)
   103 {
   104 	uint32_t data = 0xFFFFFFFF;
   106 	printf("RD32 %08X %d", address, state.romlmap);
   108 	// If ROMLMAP is set, force system to access ROM
   109 	if (!state.romlmap)
   110 		address |= 0x800000;
   112 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   113 		// ROM access
   114 		data = (((uint32_t)state.rom[(address + 0) & (ROM_SIZE - 1)] << 24) |
   115 				((uint32_t)state.rom[(address + 1) & (ROM_SIZE - 1)] << 16) |
   116 				((uint32_t)state.rom[(address + 2) & (ROM_SIZE - 1)] << 8)  |
   117 				((uint32_t)state.rom[(address + 3) & (ROM_SIZE - 1)]));
   118 	} else if (address < state.ram_size - 1) {
   119 		// RAM
   120 		data = (((uint32_t)state.ram[address + 0] << 24) |
   121 				((uint32_t)state.ram[address + 1] << 16) |
   122 				((uint32_t)state.ram[address + 2] << 8)  |
   123 				((uint32_t)state.ram[address + 3]));
   124 	}
   126 	printf(" ==> %08X\n", data);
   127 	return data;
   128 }
   130 uint32_t m68k_read_memory_16(uint32_t address)
   131 {
   132 	uint16_t data = 0xFFFF;
   134 	printf("RD16 %08X %d", address, state.romlmap);
   136 	// If ROMLMAP is set, force system to access ROM
   137 	if (!state.romlmap)
   138 		address |= 0x800000;
   140 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   141 		// ROM access
   142 		data = ((state.rom[(address + 0) & (ROM_SIZE - 1)] << 8) |
   143 				(state.rom[(address + 1) & (ROM_SIZE - 1)]));
   144 	} else if (address < state.ram_size - 1) {
   145 		// RAM
   146 		data = ((state.ram[address + 0] << 8) |
   147 				(state.ram[address + 1]));
   148 	}
   150 	printf(" ==> %04X\n", data);
   151 	return data;
   152 }
   154 uint32_t m68k_read_memory_8(uint32_t address)
   155 {
   156 	uint8_t data = 0xFF;
   158 	printf("RD 8 %08X %d ", address, state.romlmap);
   160 	// If ROMLMAP is set, force system to access ROM
   161 	if (!state.romlmap)
   162 		address |= 0x800000;
   164 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   165 		// ROM access
   166 		data = state.rom[(address + 0) & (ROM_SIZE - 1)];
   167 	} else if (address < state.ram_size) {
   168 		// RAM access
   169 		data = state.ram[address + 0];
   170 	}
   172 	printf("==> %02X\n", data);
   173 	return data;
   174 }
   176 // write m68k memory
   177 void m68k_write_memory_32(uint32_t address, uint32_t value)
   178 {
   179 	// If ROMLMAP is set, force system to access ROM
   180 	if (!state.romlmap)
   181 		address |= 0x800000;
   183 	printf("WR32 %08X %d %02X\n", address, state.romlmap, value);
   185 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   186 		// ROM access
   187 		// TODO: bus error here? can't write to rom!
   188 	} else if (address < state.ram_size) {
   189 		// RAM access
   190 		state.ram[address + 0] = (value >> 24) & 0xff;
   191 		state.ram[address + 1] = (value >> 16) & 0xff;
   192 		state.ram[address + 2] = (value >> 8)  & 0xff;
   193 		state.ram[address + 3] =  value        & 0xff;
   194 	} else {
   195 		switch (address) {
   196 			case 0xE43000:	state.romlmap = ((value & 0x8000) == 0x8000);
   197 		}
   198 	}
   199 }
   201 void m68k_write_memory_16(uint32_t address, uint32_t value)
   202 {
   203 	// If ROMLMAP is set, force system to access ROM
   204 	if (!state.romlmap)
   205 		address |= 0x800000;
   207 	printf("WR16 %08X %d %02X\n", address, state.romlmap, value);
   209 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   210 		// ROM access
   211 		// TODO: bus error here? can't write to rom!
   212 	} else if (address < state.ram_size) {
   213 		// RAM access
   214 		state.ram[address + 0] = (value >> 8)  & 0xff;
   215 		state.ram[address + 1] =  value        & 0xff;
   216 	} else {
   217 		switch (address) {
   218 			case 0xE43000:	state.romlmap = ((value & 0x8000) == 0x8000);
   219 		}
   220 	}
   221 }
   223 void m68k_write_memory_8(uint32_t address, uint32_t value)
   224 {
   225 	// If ROMLMAP is set, force system to access ROM
   226 	if (!state.romlmap)
   227 		address |= 0x800000;
   229 	printf("WR 8 %08X %d %02X\n", address, state.romlmap, value);
   231 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   232 		// ROM access
   233 		// TODO: bus error here? can't write to rom!
   234 	} else if (address < state.ram_size) {
   235 		state.ram[address] = value & 0xff;
   236 	} else {
   237 		switch (address) {
   238 			case 0xE43000:	state.romlmap = ((value & 0x80) == 0x80);
   239 		}
   240 	}
   241 }
   243 // for the disassembler
   244 uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); }
   245 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); }
   246 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); }
   248 int main(void)
   249 {
   250 	// copyright banner
   251 	printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator\n");
   252 	printf("Copyright (C) 2010 P. A. Pemberton.\n");
   253 	printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
   255 	// set up system state
   256 	// 512K of RAM
   257 	state.ram_size = 512*1024;
   258 	state_init();
   260 	// set up musashi
   261 	m68k_set_cpu_type(M68K_CPU_TYPE_68010);
   262 	m68k_pulse_reset();
   264 	char dasm[512];
   265 	m68k_disassemble(dasm, 0x80001a, M68K_CPU_TYPE_68010);
   266 	printf("%s\n", dasm);
   268 	// set up SDL
   270 	// emulation loop!
   271 	// repeat:
   272 	// 		m68k_execute()
   273 	// 		m68k_set_irq() every 60ms
   274 	printf("ran for %d cycles\n", m68k_execute(100000));
   276 	// shut down and exit
   278 	return 0;
   279 }