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

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