1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - device.c * |
3 | * Mupen64Plus homepage: https://mupen64plus.org/ * |
4 | * Copyright (C) 2016 Bobby Smiles * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | #include "device.h" |
23 | |
24 | #include "memory/memory.h" |
25 | #include "pif/pif.h" |
26 | #include "r4300/r4300_core.h" |
27 | #include "rcp/ai/ai_controller.h" |
28 | #include "rcp/mi/mi_controller.h" |
29 | #include "rcp/pi/pi_controller.h" |
30 | #include "rcp/rdp/rdp_core.h" |
31 | #include "rcp/ri/ri_controller.h" |
32 | #include "rcp/rsp/rsp_core.h" |
33 | #include "rcp/si/si_controller.h" |
34 | #include "rcp/vi/vi_controller.h" |
35 | |
36 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) |
37 | |
38 | |
39 | static void read_open_bus(void* opaque, uint32_t address, uint32_t* value) |
40 | { |
41 | *value = (address & 0xffff); |
42 | *value |= (*value << 16); |
43 | } |
44 | |
45 | static void write_open_bus(void* opaque, uint32_t address, uint32_t value, uint32_t mask) |
46 | { |
47 | } |
48 | |
49 | static void get_pi_dma_handler(struct cart* cart, struct dd_controller* dd, uint32_t address, void** opaque, const struct pi_dma_handler** handler) |
50 | { |
51 | #define RW(o, x) \ |
52 | do { \ |
53 | static const struct pi_dma_handler h = { x ## _dma_read, x ## _dma_write }; \ |
54 | *opaque = (o); \ |
55 | *handler = &h; \ |
56 | } while(0) |
57 | |
58 | if (address >= MM_CART_ROM) { |
59 | if (address >= MM_CART_DOM3) { |
60 | /* 0x1fd00000 - 0x7fffffff : dom3 addr2, cart rom (Paper Mario (U)) ??? */ |
61 | RW(cart, cart_dom3); |
62 | } |
63 | else { |
64 | /* 0x10000000 - 0x1fbfffff : dom1 addr2, cart rom */ |
65 | RW(&cart->cart_rom, cart_rom); |
66 | } |
67 | } |
68 | else if (address >= MM_DOM2_ADDR2) { |
69 | /* 0x08000000 - 0x0fffffff : dom2 addr2, cart save */ |
70 | RW(cart, cart_dom2); |
71 | } |
72 | else if (address >= MM_DOM2_ADDR1) { |
73 | /* 0x05000000 - 0x05ffffff : dom2 addr1, dd buffers */ |
74 | /* 0x06000000 - 0x07ffffff : dom1 addr1, dd rom */ |
75 | RW(dd, dd_dom); |
76 | } |
77 | #undef RW |
78 | } |
79 | |
80 | void init_device(struct device* dev, |
81 | /* memory */ |
82 | void* base, |
83 | /* r4300 */ |
84 | unsigned int emumode, |
85 | unsigned int count_per_op, |
86 | int no_compiled_jump, |
87 | int randomize_interrupt, |
88 | /* ai */ |
89 | void* aout, const struct audio_out_backend_interface* iaout, |
90 | /* si */ |
91 | unsigned int si_dma_duration, |
92 | /* rdram */ |
93 | size_t dram_size, |
94 | /* pif */ |
95 | void* jbds[PIF_CHANNELS_COUNT], |
96 | const struct joybus_device_interface* ijbds[PIF_CHANNELS_COUNT], |
97 | /* vi */ |
98 | unsigned int vi_clock, unsigned int expected_refresh_rate, |
99 | /* cart */ |
100 | void* af_rtc_clock, const struct clock_backend_interface* iaf_rtc_clock, |
101 | size_t rom_size, |
102 | uint16_t eeprom_type, |
103 | void* eeprom_storage, const struct storage_backend_interface* ieeprom_storage, |
104 | uint32_t flashram_type, |
105 | void* flashram_storage, const struct storage_backend_interface* iflashram_storage, |
106 | void* sram_storage, const struct storage_backend_interface* isram_storage, |
107 | /* dd */ |
108 | void* dd_rtc_clock, const struct clock_backend_interface* dd_rtc_iclock, |
109 | size_t dd_rom_size, |
110 | void* dd_disk, const struct storage_backend_interface* dd_idisk) |
111 | { |
112 | struct interrupt_handler interrupt_handlers[] = { |
113 | { &dev->vi, vi_vertical_interrupt_event }, /* VI */ |
114 | { &dev->r4300, compare_int_handler }, /* COMPARE */ |
115 | { &dev->r4300, check_int_handler }, /* CHECK */ |
116 | { &dev->si, si_end_of_dma_event }, /* SI */ |
117 | { &dev->pi, pi_end_of_dma_event }, /* PI */ |
118 | { &dev->r4300.cp0, special_int_handler }, /* SPECIAL */ |
119 | { &dev->ai, ai_end_of_dma_event }, /* AI */ |
120 | { &dev->sp, rsp_interrupt_event }, /* SP */ |
121 | { &dev->dp, rdp_interrupt_event }, /* DP */ |
122 | { &dev->pif, hw2_int_handler }, /* HW2 */ |
123 | { dev, nmi_int_handler }, /* NMI */ |
124 | { dev, reset_hard_handler } /* reset_hard */ |
125 | }; |
126 | |
127 | #define R(x) read_ ## x |
128 | #define W(x) write_ ## x |
129 | #define RW(x) R(x), W(x) |
130 | #define A(x,m) (x), (x) | (m) |
131 | struct mem_mapping mappings[] = { |
132 | /* clear mappings */ |
133 | { 0x00000000, 0xffffffff, M64P_MEM_NOTHING, { NULL, RW(open_bus) } }, |
134 | /* memory map */ |
135 | { A(MM_RDRAM_DRAM, dram_size-1), M64P_MEM_RDRAM, { &dev->rdram, RW(rdram_dram) } }, |
136 | { A(MM_RDRAM_REGS, 0xfffff), M64P_MEM_RDRAMREG, { &dev->rdram, RW(rdram_regs) } }, |
137 | { A(MM_RSP_MEM, 0xffff), M64P_MEM_RSPMEM, { &dev->sp, RW(rsp_mem) } }, |
138 | { A(MM_RSP_REGS, 0xffff), M64P_MEM_RSPREG, { &dev->sp, RW(rsp_regs) } }, |
139 | { A(MM_RSP_REGS2, 0xffff), M64P_MEM_RSP, { &dev->sp, RW(rsp_regs2) } }, |
140 | { A(MM_DPC_REGS, 0xffff), M64P_MEM_DP, { &dev->dp, RW(dpc_regs) } }, |
141 | { A(MM_DPS_REGS, 0xffff), M64P_MEM_DPS, { &dev->dp, RW(dps_regs) } }, |
142 | { A(MM_MI_REGS, 0xffff), M64P_MEM_MI, { &dev->mi, RW(mi_regs) } }, |
143 | { A(MM_VI_REGS, 0xffff), M64P_MEM_VI, { &dev->vi, RW(vi_regs) } }, |
144 | { A(MM_AI_REGS, 0xffff), M64P_MEM_AI, { &dev->ai, RW(ai_regs) } }, |
145 | { A(MM_PI_REGS, 0xffff), M64P_MEM_PI, { &dev->pi, RW(pi_regs) } }, |
146 | { A(MM_RI_REGS, 0xffff), M64P_MEM_RI, { &dev->ri, RW(ri_regs) } }, |
147 | { A(MM_SI_REGS, 0xffff), M64P_MEM_SI, { &dev->si, RW(si_regs) } }, |
148 | { A(MM_DOM2_ADDR1, 0xffffff), M64P_MEM_NOTHING, { NULL, RW(open_bus) } }, |
149 | { A(MM_DD_ROM, 0x1ffffff), M64P_MEM_NOTHING, { NULL, RW(open_bus) } }, |
150 | { A(MM_DOM2_ADDR2, 0x1ffff), M64P_MEM_FLASHRAMSTAT, { &dev->cart, RW(cart_dom2) } }, |
151 | { A(MM_CART_ROM, rom_size-1), M64P_MEM_ROM, { &dev->cart.cart_rom, RW(cart_rom) } }, |
152 | { A(MM_PIF_MEM, 0xffff), M64P_MEM_PIF, { &dev->pif, RW(pif_ram) } } |
153 | }; |
154 | |
155 | /* init and map DD if present */ |
156 | if (dd_rom_size > 0) { |
157 | mappings[14] = (struct mem_mapping){ A(MM_DOM2_ADDR1, 0xffffff), M64P_MEM_NOTHING, { &dev->dd, RW(dd_regs) } }; |
158 | mappings[15] = (struct mem_mapping){ A(MM_DD_ROM, dd_rom_size-1), M64P_MEM_NOTHING, { &dev->dd, RW(dd_rom) } }; |
159 | |
160 | init_dd(&dev->dd, |
161 | dd_rtc_clock, dd_rtc_iclock, |
162 | mem_base_u32(base, MM_DD_ROM), dd_rom_size, |
163 | dd_disk, dd_idisk, |
164 | &dev->r4300); |
165 | } |
166 | |
167 | struct mem_handler dbg_handler = { &dev->r4300, RW(with_bp_checks) }; |
168 | #undef A |
169 | #undef R |
170 | #undef W |
171 | #undef RW |
172 | |
173 | init_memory(&dev->mem, mappings, ARRAY_SIZE(mappings), base, &dbg_handler); |
174 | |
175 | init_rdram(&dev->rdram, mem_base_u32(base, MM_RDRAM_DRAM), dram_size, &dev->r4300); |
176 | |
177 | init_r4300(&dev->r4300, &dev->mem, &dev->mi, &dev->rdram, interrupt_handlers, |
178 | emumode, count_per_op, no_compiled_jump, randomize_interrupt); |
179 | init_rdp(&dev->dp, &dev->sp, &dev->mi, &dev->mem, &dev->rdram, &dev->r4300); |
180 | init_rsp(&dev->sp, mem_base_u32(base, MM_RSP_MEM), &dev->mi, &dev->dp, &dev->ri); |
181 | init_ai(&dev->ai, &dev->mi, &dev->ri, &dev->vi, aout, iaout); |
182 | init_mi(&dev->mi, &dev->r4300); |
183 | init_pi(&dev->pi, |
184 | get_pi_dma_handler, |
185 | &dev->cart, &dev->dd, |
186 | &dev->mi, &dev->ri, &dev->dp); |
187 | init_ri(&dev->ri, &dev->rdram); |
188 | init_si(&dev->si, si_dma_duration, &dev->mi, &dev->pif, &dev->ri); |
189 | init_vi(&dev->vi, vi_clock, expected_refresh_rate, &dev->mi, &dev->dp); |
190 | |
191 | /* FIXME: should boot on cart, unless only a disk is present, but having no cart is not yet supported by ui/core, |
192 | * so use another way of selecting boot device: |
193 | * use CART unless DD is plugged and the plugged CART is not a combo media (cart+disk). |
194 | */ |
195 | uint8_t media = *((uint8_t*)mem_base_u32(base, MM_CART_ROM) + (0x3b ^ S8)); |
196 | uint32_t rom_base = (dd_rom_size > 0 && media != 'C') |
197 | ? MM_DD_ROM |
198 | : MM_CART_ROM; |
199 | |
200 | init_pif(&dev->pif, |
201 | (uint8_t*)mem_base_u32(base, MM_PIF_MEM), |
202 | jbds, ijbds, |
203 | (uint8_t*)mem_base_u32(base, rom_base) + 0x40, |
204 | &dev->r4300); |
205 | |
206 | init_cart(&dev->cart, |
207 | af_rtc_clock, iaf_rtc_clock, |
208 | (uint8_t*)mem_base_u32(base, MM_CART_ROM), rom_size, |
209 | &dev->r4300, |
210 | eeprom_type, eeprom_storage, ieeprom_storage, |
211 | flashram_type, flashram_storage, iflashram_storage, |
212 | (const uint8_t*)dev->rdram.dram, |
213 | sram_storage, isram_storage); |
214 | } |
215 | |
216 | void poweron_device(struct device* dev) |
217 | { |
218 | size_t i; |
219 | |
220 | poweron_rdram(&dev->rdram); |
221 | poweron_r4300(&dev->r4300); |
222 | poweron_rdp(&dev->dp); |
223 | poweron_rsp(&dev->sp); |
224 | poweron_ai(&dev->ai); |
225 | poweron_mi(&dev->mi); |
226 | poweron_pi(&dev->pi); |
227 | poweron_ri(&dev->ri); |
228 | poweron_si(&dev->si); |
229 | poweron_vi(&dev->vi); |
230 | |
231 | poweron_pif(&dev->pif); |
232 | |
233 | poweron_cart(&dev->cart); |
234 | |
235 | /* poweron for controllers */ |
236 | for(i = 0; i < GAME_CONTROLLERS_COUNT; ++i) { |
237 | struct pif_channel* channel = &dev->pif.channels[i]; |
238 | |
239 | if ((channel->ijbd != NULL) && (channel->ijbd->poweron != NULL)) { |
240 | channel->ijbd->poweron(channel->jbd); |
241 | } |
242 | } |
243 | |
244 | if (dev->dd.rom != NULL) { |
245 | poweron_dd(&dev->dd); |
246 | } |
247 | } |
248 | |
249 | void run_device(struct device* dev) |
250 | { |
251 | /* device execution is driven by the r4300 */ |
252 | run_r4300(&dev->r4300); |
253 | } |
254 | |
255 | void stop_device(struct device* dev) |
256 | { |
257 | /* set stop flag so that r4300 execution will be stopped at next interrupt */ |
258 | *r4300_stop(&dev->r4300) = 1; |
259 | } |
260 | |
261 | void hard_reset_device(struct device* dev) |
262 | { |
263 | /* set reset hard flag so reset_hard will be called at next interrupt */ |
264 | dev->r4300.reset_hard_job = 1; |
265 | } |
266 | |
267 | void soft_reset_device(struct device* dev) |
268 | { |
269 | /* schedule HW2 interrupt now and an NMI after 1/2 seconds */ |
270 | add_interrupt_event(&dev->r4300.cp0, HW2_INT, 0); |
271 | add_interrupt_event(&dev->r4300.cp0, NMI_INT, 50000000); |
272 | } |
273 | |