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