src/main.c

Sun, 28 Nov 2010 22:01:45 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 28 Nov 2010 22:01:45 +0000
changeset 10
dbf4ba9563c9
parent 9
3e99497dca33
child 11
67bf6abb6e79
permissions
-rw-r--r--

rework to use byte arrays to store ROM and RAM

     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
    44 	// TODO: make sure ram size selection is valid (512K, 1MB, 1.5MB, 2MB, 2.5MB, 3MB or 4MB)!
    45 	state.ram = malloc(state.ram_size);
    46 	if (state.ram == NULL)
    47 		return -1;
    49 	// Load ROMs
    50 	FILE *r14c, *r15c;
    51 	r14c = fopen("roms/14c.bin", "rb");
    52 	if (r14c == NULL) FAIL("unable to open roms/14c.bin");
    53 	r15c = fopen("roms/15c.bin", "rb");
    54 	if (r15c == NULL) FAIL("unable to open roms/15c.bin");
    56 	// get ROM file size
    57 	fseek(r14c, 0, SEEK_END);
    58 	size_t romlen = ftell(r14c);
    59 	fseek(r14c, 0, SEEK_SET);
    60 	fseek(r15c, 0, SEEK_END);
    61 	size_t romlen2 = ftell(r15c);
    62 	fseek(r15c, 0, SEEK_SET);
    63 	if (romlen2 != romlen) FAIL("ROMs are not the same size!");
    64 	if ((romlen + romlen2) > ROM_SIZE) FAIL("ROMs are too large to fit in memory!");
    66 	// sanity checks completed; load the ROMs!
    67 	uint8_t *romdat1, *romdat2;
    68 	romdat1 = malloc(romlen);
    69 	romdat2 = malloc(romlen2);
    70 	fread(romdat1, 1, romlen, r15c);
    71 	fread(romdat2, 1, romlen2, r14c);
    73 	// convert the ROM data
    74 	for (size_t i=0; i<(romlen + romlen2); i+=2) {
    75 		state.rom[i+0] = romdat1[i/2];
    76 		state.rom[i+1] = romdat2[i/2];
    77 	}
    79 	for (size_t i=0; i<16; i++) printf("%02X ", state.rom[i]);
    80 	printf("\n");
    82 	// TODO: if ROM buffer not filled, repeat the ROM data we read until it is.
    84 	// free the data arrays and close the files
    85 	free(romdat1);
    86 	free(romdat2);
    87 	fclose(r14c);
    88 	fclose(r15c);
    90 	return 0;
    91 }
    93 void state_done()
    94 {
    95 	if (state.ram != NULL)
    96 		free(state.ram);
    97 }
    99 // read m68k memory
   100 uint32_t m68k_read_memory_32(uint32_t address)
   101 {
   102 	uint32_t data = 0xFFFFFFFF;
   104 	printf("RD32 %08X %d", address, state.romlmap);
   106 	// If ROMLMAP is set, force system to access ROM
   107 	if (!state.romlmap)
   108 		address |= 0x800000;
   110 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   111 		// ROM access
   112 		data = (((uint32_t)state.rom[(address + 0) & (ROM_SIZE - 1)] << 24) |
   113 				((uint32_t)state.rom[(address + 1) & (ROM_SIZE - 1)] << 16) |
   114 				((uint32_t)state.rom[(address + 2) & (ROM_SIZE - 1)] << 8)  |
   115 				((uint32_t)state.rom[(address + 3) & (ROM_SIZE - 1)]));
   116 	} else if (address < state.ram_size - 1) {
   117 		// RAM
   118 		data = (((uint32_t)state.ram[address + 0] << 24) |
   119 				((uint32_t)state.ram[address + 1] << 16) |
   120 				((uint32_t)state.ram[address + 2] << 8)  |
   121 				((uint32_t)state.ram[address + 3]));
   122 	}
   124 	printf(" ==> %08X\n", data);
   125 	return data;
   126 }
   128 uint32_t m68k_read_memory_16(uint32_t address)
   129 {
   130 	uint16_t data = 0xFFFF;
   132 	printf("RD16 %08X %d", address, state.romlmap);
   134 	// If ROMLMAP is set, force system to access ROM
   135 	if (!state.romlmap)
   136 		address |= 0x800000;
   138 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   139 		// ROM access
   140 		data = ((state.rom[(address + 0) & (ROM_SIZE - 1)] << 8) |
   141 				(state.rom[(address + 1) & (ROM_SIZE - 1)]));
   142 	} else if (address < state.ram_size - 1) {
   143 		// RAM
   144 		data = ((state.ram[address + 0] << 8) |
   145 				(state.ram[address + 1]));
   146 	}
   148 	printf(" ==> %04X\n", data);
   149 	return data;
   150 }
   152 uint32_t m68k_read_memory_8(uint32_t address)
   153 {
   154 	uint8_t data = 0xFF;
   156 	printf("RD 8 %08X %d ", address, state.romlmap);
   158 	// If ROMLMAP is set, force system to access ROM
   159 	if (!state.romlmap)
   160 		address |= 0x800000;
   162 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   163 		// ROM access
   164 		data = state.rom[(address + 0) & (ROM_SIZE - 1)];
   165 	} else if (address < state.ram_size) {
   166 		// RAM access
   167 		data = state.ram[address + 0];
   168 	}
   170 	printf("==> %02X\n", data);
   171 	return data;
   172 }
   174 // write m68k memory
   175 void m68k_write_memory_32(uint32_t address, uint32_t value)
   176 {
   177 	// If ROMLMAP is set, force system to access ROM
   178 	if (!state.romlmap)
   179 		address |= 0x800000;
   181 	printf("WR32 %08X %d %02X\n", address, state.romlmap, value);
   183 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   184 		// ROM access
   185 		// TODO: bus error here? can't write to rom!
   186 	} else if (address < state.ram_size) {
   187 		// RAM access
   188 		state.ram[address + 0] = (value >> 24) & 0xff;
   189 		state.ram[address + 1] = (value >> 16) & 0xff;
   190 		state.ram[address + 2] = (value >> 8)  & 0xff;
   191 		state.ram[address + 3] =  value        & 0xff;
   192 	} else {
   193 		switch (address) {
   194 			case 0xE43000:	state.romlmap = ((value & 0x8000) == 0x8000);
   195 		}
   196 	}
   197 }
   199 void m68k_write_memory_16(uint32_t address, uint32_t value)
   200 {
   201 	// If ROMLMAP is set, force system to access ROM
   202 	if (!state.romlmap)
   203 		address |= 0x800000;
   205 	printf("WR16 %08X %d %02X\n", address, state.romlmap, value);
   207 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   208 		// ROM access
   209 		// TODO: bus error here? can't write to rom!
   210 	} else if (address < state.ram_size) {
   211 		// RAM access
   212 		state.ram[address + 0] = (value >> 8)  & 0xff;
   213 		state.ram[address + 1] =  value        & 0xff;
   214 	} else {
   215 		switch (address) {
   216 			case 0xE43000:	state.romlmap = ((value & 0x8000) == 0x8000);
   217 		}
   218 	}
   219 }
   221 void m68k_write_memory_8(uint32_t address, uint32_t value)
   222 {
   223 	// If ROMLMAP is set, force system to access ROM
   224 	if (!state.romlmap)
   225 		address |= 0x800000;
   227 	printf("WR 8 %08X %d %02X\n", address, state.romlmap, value);
   229 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   230 		// ROM access
   231 		// TODO: bus error here? can't write to rom!
   232 	} else if (address < state.ram_size) {
   233 		state.ram[address] = value & 0xff;
   234 	} else {
   235 		switch (address) {
   236 			case 0xE43000:	state.romlmap = ((value & 0x80) == 0x80);
   237 		}
   238 	}
   239 }
   241 // for the disassembler
   242 uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); }
   243 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); }
   244 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); }
   246 int main(void)
   247 {
   248 	// copyright banner
   249 	printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator\n");
   250 	printf("Copyright (C) 2010 P. A. Pemberton.\n");
   251 	printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
   253 	// set up system state
   254 	// 512K of RAM
   255 	state.ram_size = 512*1024;
   256 	state_init();
   258 	// set up musashi
   259 	m68k_set_cpu_type(M68K_CPU_TYPE_68010);
   260 	m68k_pulse_reset();
   262 	char dasm[512];
   263 	m68k_disassemble(dasm, 0x80001a, M68K_CPU_TYPE_68010);
   264 	printf("%s\n", dasm);
   266 	// set up SDL
   268 	// emulation loop!
   269 	// repeat:
   270 	// 		m68k_execute()
   271 	// 		m68k_set_irq() every 60ms
   272 	printf("ran for %d cycles\n", m68k_execute(100000));
   274 	// shut down and exit
   276 	return 0;
   277 }