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

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