Sun, 28 Nov 2010 20:52:53 +0000
fix memory read stuff, now need to deal with memory write
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/2)
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 uint16_t rom[ROM_SIZE];
26 // Main system RAM
27 uint16_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++) {
78 state.rom[i] = ((romdat1[i] << 8) | (romdat2[i]));
79 }
81 // free the data arrays and close the files
82 free(romdat1);
83 free(romdat2);
84 fclose(r14c);
85 fclose(r15c);
87 return 0;
88 }
90 void state_done()
91 {
92 if (state.ram != NULL)
93 free(state.ram);
94 }
96 // read m68k memory
97 // TODO: refactor musashi to use stdint, and properly sized integers!
98 // TODO: find a way to make musashi use function pointers instead of hard coded callbacks, maybe use a context struct too
99 uint32_t m68k_read_memory_32(uint32_t address)
100 {
101 uint32_t data = 0xFFFFFFFF;
103 printf("RD32 %08X %d", address, state.romlmap);
105 // If ROMLMAP is set, force system to access ROM
106 if (!state.romlmap)
107 address |= 0x800000;
109 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
110 // ROM access
111 data = ((state.rom[(address & (ROM_SIZE-1)) / 2] << 16) | (state.rom[((address & (ROM_SIZE-1)) / 2)+1]));
112 } else if (address <= 0x3FFFFF) {
113 // RAM
114 data = state.ram[(address & state.ram_addr_mask) / 2];
115 }
117 printf(" ==> %04X\n", data);
118 return data;
119 }
121 uint32_t m68k_read_memory_16(uint32_t address)
122 {
123 uint16_t data = 0xFFFF;
125 printf("RD16 %08X %d", address, state.romlmap);
127 // If ROMLMAP is set, force system to access ROM
128 if (!state.romlmap)
129 address |= 0x800000;
131 data = (m68k_read_memory_32(address) >> 16) & 0xFFFF;
133 printf(" ==> %04X\n", data);
134 return data;
135 }
137 uint32_t m68k_read_memory_8(uint32_t address)
138 {
139 uint8_t data = 0xFF;
141 printf("RD 8 %08X %d ", address, state.romlmap);
143 // If ROMLMAP is set, force system to access ROM
144 if (!state.romlmap)
145 address |= 0x800000;
147 data = m68k_read_memory_32(address) & 0xFF;
149 printf("==> %02X\n", data);
150 return data;
151 }
153 // write m68k memory
154 void m68k_write_memory_32(uint32_t address, uint32_t value)
155 {
156 // If ROMLMAP is set, force system to access ROM
157 if (!state.romlmap)
158 address |= 0x800000;
160 printf("WR32 %08X %d %02X\n", address, state.romlmap, value);
162 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
163 // ROM access
164 // TODO: bus error here? can't write to rom!
165 } else if (address <= 0x3FFFFF) {
166 // RAM
167 state.ram[(address & state.ram_addr_mask) / 2] = (value >> 16);
168 state.ram[((address & state.ram_addr_mask) / 2)+1] = value & 0xffff;
169 } else {
170 switch (address) {
171 case 0xE43000: state.romlmap = ((value & 0x8000) == 0x8000);
172 }
173 }
174 }
176 void m68k_write_memory_16(uint32_t address, uint32_t value)
177 {
178 // If ROMLMAP is set, force system to access ROM
179 if (!state.romlmap)
180 address |= 0x800000;
182 printf("WR16 %08X %d %02X\n", address, state.romlmap, value);
184 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
185 // ROM access
186 // TODO: bus error here? can't write to rom!
187 } else if (address <= 0x3FFFFF) {
188 // RAM
189 state.ram[(address & state.ram_addr_mask) / 2] = value & 0xFFFF;
190 } else {
191 switch (address) {
192 case 0xE43000: state.romlmap = ((value & 0x8000) == 0x8000);
193 }
194 }
195 }
197 void m68k_write_memory_8(uint32_t address, uint32_t value)
198 {
199 // If ROMLMAP is set, force system to access ROM
200 if (!state.romlmap)
201 address |= 0x800000;
203 printf("WR 8 %08X %d %02X\n", address, state.romlmap, value);
205 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
206 // ROM access
207 // TODO: bus error here? can't write to rom!
208 } else if (address <= 0x3FFFFF) {
209 // RAM
210 switch (address & 3) {
211 // FIXME
212 case 3: state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFFFF00) | (value & 0xFF);
213 case 2: state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFFFF00FF) | ((value & 0xFF) << 8);
214 case 1: state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0xFF00FFFF) | ((value & 0xFF) << 16);
215 case 0: state.ram[(address & state.ram_addr_mask) / 4] = (state.ram[(address & state.ram_addr_mask) / 4] & 0x00FFFFFF) | ((value & 0xFF) << 24);
216 }
217 } else {
218 switch (address) {
219 case 0xE43000: state.romlmap = ((value & 0x80) == 0x80);
220 }
221 }
222 }
224 uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); }
225 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); }
226 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); }
228 int main(void)
229 {
230 // copyright banner
231 printf("FreeBee: A Quick-and-Dirty AT&T 3B1 Emulator\n");
232 printf("Copyright (C) 2010 P. A. Pemberton.\n");
233 printf("Musashi M680x0 emulator engine developed by Karl Stenerud <kstenerud@gmail.com>\n");
235 // set up system state
236 // 512K of RAM
237 state.ram_size = 512*1024;
238 state_init();
240 // set up musashi
241 m68k_set_cpu_type(M68K_CPU_TYPE_68010);
242 m68k_pulse_reset();
244 char dasm[512];
245 m68k_disassemble(dasm, 0x80001a, M68K_CPU_TYPE_68010);
246 printf("%s\n", dasm);
248 // set up SDL
250 // emulation loop!
251 // repeat:
252 // m68k_execute()
253 // m68k_set_irq() every 60ms
254 printf("ran for %d cycles\n", m68k_execute(100000));
256 // shut down and exit
258 return 0;
259 }