Sun, 28 Nov 2010 22:01:45 +0000
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 }