2961
|
1 /* Copyright (C) 2006 yopyop
|
|
2 yopyop156@ifrance.com
|
|
3 yopyop156.ifrance.com
|
|
4
|
|
5 This file is part of DeSmuME
|
|
6
|
|
7 DeSmuME is free software; you can redistribute it and/or modify
|
|
8 it under the terms of the GNU General Public License as published by
|
|
9 the Free Software Foundation; either version 2 of the License, or
|
|
10 (at your option) any later version.
|
|
11
|
|
12 DeSmuME is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with DeSmuME; if not, write to the Free Software
|
|
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
20 */
|
|
21
|
|
22 #include <string.h>
|
|
23 #include <stdlib.h>
|
|
24
|
|
25 #include "NDSSystem.h"
|
|
26 #include "MMU.h"
|
|
27 //#include "cflash.h"
|
|
28
|
|
29 //#include "ROMReader.h"
|
|
30
|
|
31 /* the count of bytes copied from the firmware into memory */
|
|
32 #define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70
|
|
33
|
|
34 NDSSystem nds;
|
|
35
|
|
36 static u32
|
|
37 calc_CRC16( u32 start, const u8 *data, int count) {
|
|
38 int i,j;
|
|
39 u32 crc = start & 0xffff;
|
|
40 static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
|
|
41 for(i = 0; i < count; i++)
|
|
42 {
|
|
43 crc = crc ^ data[i];
|
|
44
|
|
45 for(j = 0; j < 8; j++) {
|
|
46 int do_bit = 0;
|
|
47
|
|
48 if ( crc & 0x1)
|
|
49 do_bit = 1;
|
|
50
|
|
51 crc = crc >> 1;
|
|
52
|
|
53 if ( do_bit) {
|
|
54 crc = crc ^ (val[j] << (7-j));
|
|
55 }
|
|
56 }
|
|
57 }
|
|
58 return crc;
|
|
59 }
|
|
60
|
|
61 static int
|
|
62 copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) {
|
|
63 /*
|
|
64 * Determine which of the two user settings in the firmware is the current
|
|
65 * and valid one and then copy this into the destination buffer.
|
|
66 *
|
|
67 * The current setting will have a greater count.
|
|
68 * Settings are only valid if its CRC16 is correct.
|
|
69 */
|
|
70 int user1_valid = 0;
|
|
71 int user2_valid = 0;
|
|
72 u32 user_settings_offset;
|
|
73 u32 fw_crc;
|
|
74 u32 crc;
|
|
75 int copy_good = 0;
|
|
76
|
|
77 user_settings_offset = fw_data[0x20];
|
|
78 user_settings_offset |= fw_data[0x21] << 8;
|
|
79 user_settings_offset <<= 3;
|
|
80
|
|
81 if ( user_settings_offset <= 0x3FE00) {
|
|
82 s32 copy_settings_offset = -1;
|
|
83
|
|
84 crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset],
|
|
85 NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
|
|
86 fw_crc = fw_data[user_settings_offset + 0x72];
|
|
87 fw_crc |= fw_data[user_settings_offset + 0x73] << 8;
|
|
88 if ( crc == fw_crc) {
|
|
89 user1_valid = 1;
|
|
90 }
|
|
91
|
|
92 crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100],
|
|
93 NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
|
|
94 fw_crc = fw_data[user_settings_offset + 0x100 + 0x72];
|
|
95 fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8;
|
|
96 if ( crc == fw_crc) {
|
|
97 user2_valid = 1;
|
|
98 }
|
|
99
|
|
100 if ( user1_valid) {
|
|
101 if ( user2_valid) {
|
|
102 u16 count1, count2;
|
|
103
|
|
104 count1 = fw_data[user_settings_offset + 0x70];
|
|
105 count1 |= fw_data[user_settings_offset + 0x71] << 8;
|
|
106
|
|
107 count2 = fw_data[user_settings_offset + 0x100 + 0x70];
|
|
108 count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8;
|
|
109
|
|
110 if ( count2 > count1) {
|
|
111 copy_settings_offset = user_settings_offset + 0x100;
|
|
112 }
|
|
113 else {
|
|
114 copy_settings_offset = user_settings_offset;
|
|
115 }
|
|
116 }
|
|
117 else {
|
|
118 copy_settings_offset = user_settings_offset;
|
|
119 }
|
|
120 }
|
|
121 else if ( user2_valid) {
|
|
122 /* copy the second user settings */
|
|
123 copy_settings_offset = user_settings_offset + 0x100;
|
|
124 }
|
|
125
|
|
126 if ( copy_settings_offset > 0) {
|
|
127 memcpy( dest_buffer, &fw_data[copy_settings_offset],
|
|
128 NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
|
|
129 copy_good = 1;
|
|
130 }
|
|
131 }
|
|
132
|
|
133 return copy_good;
|
|
134 }
|
|
135
|
|
136
|
|
137 #ifdef GDB_STUB
|
|
138 int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
|
|
139 struct armcpu_ctrl_iface **arm9_ctrl_iface,
|
|
140 struct armcpu_memory_iface *arm7_mem_if,
|
|
141 struct armcpu_ctrl_iface **arm7_ctrl_iface) {
|
|
142 #else
|
|
143 int NDS_Init( void) {
|
|
144 #endif
|
|
145 nds.ARM9Cycle = 0;
|
|
146 nds.ARM7Cycle = 0;
|
|
147 nds.cycles = 0;
|
|
148 MMU_Init();
|
|
149 nds.nextHBlank = 3168;
|
|
150 nds.VCount = 0;
|
|
151 nds.lignerendu = FALSE;
|
|
152
|
|
153 if (Screen_Init(GFXCORE_DUMMY) != 0)
|
|
154 return -1;
|
|
155
|
|
156 #ifdef GDB_STUB
|
|
157 armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
|
|
158 armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
|
|
159 #else
|
|
160 armcpu_new(&NDS_ARM7,1);
|
|
161 armcpu_new(&NDS_ARM9,0);
|
|
162 #endif
|
|
163
|
|
164 if (SPU_Init(SNDCORE_DUMMY, 735) != 0)
|
|
165 return -1;
|
|
166
|
|
167 #ifdef EXPERIMENTAL_WIFI
|
|
168 WIFI_Init(&wifiMac) ;
|
|
169 #endif
|
|
170
|
|
171 return 0;
|
|
172 }
|
|
173
|
|
174 static void armcpu_deinit(armcpu_t *armcpu)
|
|
175 {
|
|
176 if(armcpu->coproc[15])
|
|
177 {
|
|
178 free(armcpu->coproc[15]);
|
|
179 armcpu->coproc[15] = 0;
|
|
180 }
|
|
181 }
|
|
182
|
|
183 void NDS_DeInit(void) {
|
|
184 if(MMU.CART_ROM != MMU.UNUSED_RAM)
|
|
185 NDS_FreeROM();
|
|
186
|
|
187 armcpu_deinit(&NDS_ARM7);
|
|
188 armcpu_deinit(&NDS_ARM9);
|
|
189
|
|
190 nds.nextHBlank = 3168;
|
|
191 SPU_DeInit();
|
|
192 Screen_DeInit();
|
|
193 MMU_DeInit();
|
|
194 }
|
|
195
|
|
196 BOOL NDS_SetROM(u8 * rom, u32 mask)
|
|
197 {
|
|
198 MMU_setRom(rom, mask);
|
|
199
|
|
200 return TRUE;
|
|
201 }
|
|
202
|
|
203 NDS_header * NDS_getROMHeader(void)
|
|
204 {
|
|
205 NDS_header * header = malloc(sizeof(NDS_header));
|
|
206
|
|
207 memcpy(header->gameTile, MMU.CART_ROM, 12);
|
|
208 memcpy(header->gameCode, MMU.CART_ROM + 12, 4);
|
|
209 header->makerCode = T1ReadWord(MMU.CART_ROM, 16);
|
|
210 header->unitCode = MMU.CART_ROM[18];
|
|
211 header->deviceCode = MMU.CART_ROM[19];
|
|
212 header->cardSize = MMU.CART_ROM[20];
|
|
213 memcpy(header->cardInfo, MMU.CART_ROM + 21, 8);
|
|
214 header->flags = MMU.CART_ROM[29];
|
|
215 header->ARM9src = T1ReadLong(MMU.CART_ROM, 32);
|
|
216 header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36);
|
|
217 header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40);
|
|
218 header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44);
|
|
219 header->ARM7src = T1ReadLong(MMU.CART_ROM, 48);
|
|
220 header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52);
|
|
221 header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56);
|
|
222 header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60);
|
|
223 header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64);
|
|
224 header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68);
|
|
225 header->FATOff = T1ReadLong(MMU.CART_ROM, 72);
|
|
226 header->FATSize = T1ReadLong(MMU.CART_ROM, 76);
|
|
227 header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80);
|
|
228 header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84);
|
|
229 header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88);
|
|
230 header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92);
|
|
231 header->unknown2a = T1ReadLong(MMU.CART_ROM, 96);
|
|
232 header->unknown2b = T1ReadLong(MMU.CART_ROM, 100);
|
|
233 header->IconOff = T1ReadLong(MMU.CART_ROM, 104);
|
|
234 header->CRC16 = T1ReadWord(MMU.CART_ROM, 108);
|
|
235 header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110);
|
|
236 header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112);
|
|
237 header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116);
|
|
238 memcpy(header->unknown3c, MMU.CART_ROM + 120, 8);
|
|
239 header->ROMSize = T1ReadLong(MMU.CART_ROM, 128);
|
|
240 header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132);
|
|
241 memcpy(header->unknown5, MMU.CART_ROM + 136, 56);
|
|
242 memcpy(header->logo, MMU.CART_ROM + 192, 156);
|
|
243 header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
|
|
244 header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
|
|
245 memcpy(header->reserved, MMU.CART_ROM + 352, 160);
|
|
246
|
|
247 return header;
|
|
248
|
|
249 //return (NDS_header *)MMU.CART_ROM;
|
|
250 }
|
|
251
|
|
252
|
|
253
|
|
254 void NDS_FreeROM(void)
|
|
255 {
|
|
256 if (MMU.CART_ROM != MMU.UNUSED_RAM)
|
|
257 free(MMU.CART_ROM);
|
|
258 MMU_unsetRom();
|
|
259 // if (MMU.bupmem.fp)
|
|
260 // fclose(MMU.bupmem.fp);
|
|
261 // MMU.bupmem.fp = NULL;
|
|
262 }
|
|
263
|
|
264
|
|
265
|
|
266 void NDS_Reset( void)
|
|
267 {
|
|
268 BOOL oldexecute=execute;
|
|
269 int i;
|
|
270 u32 src;
|
|
271 u32 dst;
|
|
272 NDS_header * header = NDS_getROMHeader();
|
|
273
|
|
274 if (!header) return ;
|
|
275
|
|
276 execute = FALSE;
|
|
277
|
|
278 MMU_clearMem();
|
|
279
|
|
280 src = header->ARM9src;
|
|
281 dst = header->ARM9cpy;
|
|
282
|
|
283 for(i = 0; i < (header->ARM9binSize>>2); ++i)
|
|
284 {
|
|
285 MMU_write32(0, dst, T1ReadLong(MMU.CART_ROM, src));
|
|
286 dst += 4;
|
|
287 src += 4;
|
|
288 }
|
|
289
|
|
290 src = header->ARM7src;
|
|
291 dst = header->ARM7cpy;
|
|
292
|
|
293 for(i = 0; i < (header->ARM7binSize>>2); ++i)
|
|
294 {
|
|
295 MMU_write32(1, dst, T1ReadLong(MMU.CART_ROM, src));
|
|
296 dst += 4;
|
|
297 src += 4;
|
|
298 }
|
|
299
|
|
300 armcpu_init(&NDS_ARM7, header->ARM7exe);
|
|
301 armcpu_init(&NDS_ARM9, header->ARM9exe);
|
|
302
|
|
303 nds.ARM9Cycle = 0;
|
|
304 nds.ARM7Cycle = 0;
|
|
305 nds.cycles = 0;
|
|
306 memset(nds.timerCycle, 0, sizeof(s32) * 2 * 4);
|
|
307 memset(nds.timerOver, 0, sizeof(BOOL) * 2 * 4);
|
|
308 nds.nextHBlank = 3168;
|
|
309 nds.VCount = 0;
|
|
310 nds.old = 0;
|
|
311 nds.diff = 0;
|
|
312 nds.lignerendu = FALSE;
|
|
313 nds.touchX = nds.touchY = 0;
|
|
314
|
|
315 MMU_write16(0, 0x04000130, 0x3FF);
|
|
316 MMU_write16(1, 0x04000130, 0x3FF);
|
|
317 MMU_write8(1, 0x04000136, 0x43);
|
|
318
|
|
319 /*
|
|
320 * Setup a copy of the firmware user settings in memory.
|
|
321 * (this is what the DS firmware would do).
|
|
322 */
|
|
323 {
|
|
324 u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
|
|
325 int fw_index;
|
|
326
|
|
327 if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) {
|
|
328 for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) {
|
|
329 MMU_write8( 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]);
|
|
330 }
|
|
331 }
|
|
332 }
|
|
333
|
|
334 // Copy the whole header to Main RAM 0x27FFE00 on startup.
|
|
335 // Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader
|
|
336 for (i = 0; i < ((0x170+0x90)/4); i++)
|
|
337 {
|
|
338 MMU_write32 (0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
|
|
339 }
|
|
340
|
|
341 MainScreen.offset = 0;
|
|
342 SubScreen.offset = 192;
|
|
343
|
|
344 //MMU_write32(0, 0x02007FFC, 0xE92D4030);
|
|
345
|
|
346 //ARM7 BIOS IRQ HANDLER
|
|
347 MMU_write32(1, 0x00, 0xE25EF002);
|
|
348 MMU_write32(1, 0x04, 0xEAFFFFFE);
|
|
349 MMU_write32(1, 0x18, 0xEA000000);
|
|
350 MMU_write32(1, 0x20, 0xE92D500F);
|
|
351 MMU_write32(1, 0x24, 0xE3A00301);
|
|
352 MMU_write32(1, 0x28, 0xE28FE000);
|
|
353 MMU_write32(1, 0x2C, 0xE510F004);
|
|
354 MMU_write32(1, 0x30, 0xE8BD500F);
|
|
355 MMU_write32(1, 0x34, 0xE25EF004);
|
|
356
|
|
357 //ARM9 BIOS IRQ HANDLER
|
|
358 MMU_write32(0, 0xFFFF0018, 0xEA000000);
|
|
359 MMU_write32(0, 0xFFFF0020, 0xE92D500F);
|
|
360 MMU_write32(0, 0xFFFF0024, 0xEE190F11);
|
|
361 MMU_write32(0, 0xFFFF0028, 0xE1A00620);
|
|
362 MMU_write32(0, 0xFFFF002C, 0xE1A00600);
|
|
363 MMU_write32(0, 0xFFFF0030, 0xE2800C40);
|
|
364 MMU_write32(0, 0xFFFF0034, 0xE28FE000);
|
|
365 MMU_write32(0, 0xFFFF0038, 0xE510F004);
|
|
366 MMU_write32(0, 0xFFFF003C, 0xE8BD500F);
|
|
367 MMU_write32(0, 0xFFFF0040, 0xE25EF004);
|
|
368
|
|
369 MMU_write32(0, 0x0000004, 0xE3A0010E);
|
|
370 MMU_write32(0, 0x0000008, 0xE3A01020);
|
|
371 // MMU_write32(0, 0x000000C, 0xE1B02110);
|
|
372 MMU_write32(0, 0x000000C, 0xE1B02040);
|
|
373 MMU_write32(0, 0x0000010, 0xE3B02020);
|
|
374 // MMU_write32(0, 0x0000010, 0xE2100202);
|
|
375
|
|
376 free(header);
|
|
377
|
|
378 GPU_Reset(MainScreen.gpu, 0);
|
|
379 GPU_Reset(SubScreen.gpu, 1);
|
|
380 SPU_Reset();
|
|
381
|
|
382 execute = oldexecute;
|
|
383 }
|
|
384
|
|
385 static void dma_check(void)
|
|
386 {
|
|
387 if((MMU.DMAing[0][0])&&(MMU.DMACycle[0][0]<=nds.cycles))
|
|
388 {
|
|
389 T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
|
|
390 if((MMU.DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(8);
|
|
391 MMU.DMAing[0][0] = FALSE;
|
|
392 }
|
|
393
|
|
394 if((MMU.DMAing[0][1])&&(MMU.DMACycle[0][1]<=nds.cycles))
|
|
395 {
|
|
396 T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
|
|
397 if((MMU.DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(9);
|
|
398 MMU.DMAing[0][1] = FALSE;
|
|
399 }
|
|
400
|
|
401 if((MMU.DMAing[0][2])&&(MMU.DMACycle[0][2]<=nds.cycles))
|
|
402 {
|
|
403 T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
|
|
404 if((MMU.DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(10);
|
|
405 MMU.DMAing[0][2] = FALSE;
|
|
406 }
|
|
407
|
|
408 if((MMU.DMAing[0][3])&&(MMU.DMACycle[0][3]<=nds.cycles))
|
|
409 {
|
|
410 T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
|
|
411 if((MMU.DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(11);
|
|
412 MMU.DMAing[0][3] = FALSE;
|
|
413 }
|
|
414
|
|
415 if((MMU.DMAing[1][0])&&(MMU.DMACycle[1][0]<=nds.cycles))
|
|
416 {
|
|
417 T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
|
|
418 if((MMU.DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(8);
|
|
419 MMU.DMAing[1][0] = FALSE;
|
|
420 }
|
|
421
|
|
422 if((MMU.DMAing[1][1])&&(MMU.DMACycle[1][1]<=nds.cycles))
|
|
423 {
|
|
424 T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
|
|
425 if((MMU.DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(9);
|
|
426 MMU.DMAing[1][1] = FALSE;
|
|
427 }
|
|
428
|
|
429 if((MMU.DMAing[1][2])&&(MMU.DMACycle[1][2]<=nds.cycles))
|
|
430 {
|
|
431 T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
|
|
432 if((MMU.DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(10);
|
|
433 MMU.DMAing[1][2] = FALSE;
|
|
434 }
|
|
435
|
|
436 if((MMU.DMAing[1][3])&&(MMU.DMACycle[1][3]<=nds.cycles))
|
|
437 {
|
|
438 T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
|
|
439 if((MMU.DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(11);
|
|
440 MMU.DMAing[1][3] = FALSE;
|
|
441 }
|
|
442
|
|
443 if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0]))
|
|
444 {
|
|
445 #ifdef GDB_STUB
|
|
446 if ( armcpu_flagIrq( &NDS_ARM9))
|
|
447 #else
|
|
448 if ( armcpu_irqExeption(&NDS_ARM9))
|
|
449 #endif
|
|
450 {
|
|
451 nds.ARM9Cycle = nds.cycles;
|
|
452 }
|
|
453 }
|
|
454
|
|
455 if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1]))
|
|
456 {
|
|
457 #ifdef GDB_STUB
|
|
458 if ( armcpu_flagIrq( &NDS_ARM7))
|
|
459 #else
|
|
460 if ( armcpu_irqExeption(&NDS_ARM7))
|
|
461 #endif
|
|
462 {
|
|
463 nds.ARM7Cycle = nds.cycles;
|
|
464 }
|
|
465 }
|
|
466
|
|
467 }
|
|
468
|
|
469 static void timer_check(void)
|
|
470 {
|
|
471 int p, t;
|
|
472 for (p = 0; p < 2; p++)
|
|
473 {
|
|
474 for (t = 0; t < 4; t++)
|
|
475 {
|
|
476 nds.timerOver[p][t] = 0;
|
|
477 if(MMU.timerON[p][t])
|
|
478 {
|
|
479 if(MMU.timerRUN[p][t])
|
|
480 {
|
|
481 switch(MMU.timerMODE[p][t])
|
|
482 {
|
|
483 case 0xFFFF :
|
|
484 if(t > 0 && nds.timerOver[p][t - 1])
|
|
485 {
|
|
486 ++(MMU.timer[p][t]);
|
|
487 nds.timerOver[p][t] = !MMU.timer[p][t];
|
|
488 if (nds.timerOver[p][t])
|
|
489 {
|
|
490 if (p == 0)
|
|
491 {
|
|
492 if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
|
|
493 NDS_makeARM9Int(3 + t);
|
|
494 }
|
|
495 else
|
|
496 {
|
|
497 if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
|
|
498 NDS_makeARM7Int(3 + t);
|
|
499 }
|
|
500 MMU.timer[p][t] = MMU.timerReload[p][t];
|
|
501 }
|
|
502 }
|
|
503 break;
|
|
504 default :
|
|
505 {
|
|
506 nds.diff = (nds.cycles >> MMU.timerMODE[p][t]) - (nds.timerCycle[p][t] >> MMU.timerMODE[p][t]);
|
|
507 nds.old = MMU.timer[p][t];
|
|
508 MMU.timer[p][t] += nds.diff;
|
|
509 nds.timerCycle[p][t] += nds.diff << MMU.timerMODE[p][t];
|
|
510 nds.timerOver[p][t] = nds.old >= MMU.timer[p][t];
|
|
511 if(nds.timerOver[p][t])
|
|
512 {
|
|
513 if (p == 0)
|
|
514 {
|
|
515 if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
|
|
516 NDS_makeARM9Int(3 + t);
|
|
517 }
|
|
518 else
|
|
519 {
|
|
520 if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
|
|
521 NDS_makeARM7Int(3 + t);
|
|
522 }
|
|
523 MMU.timer[p][t] = MMU.timerReload[p][t] + MMU.timer[p][t] - nds.old;
|
|
524 }
|
|
525 }
|
|
526 break;
|
|
527 }
|
|
528 }
|
|
529 else
|
|
530 {
|
|
531 MMU.timerRUN[p][t] = TRUE;
|
|
532 nds.timerCycle[p][t] = nds.cycles;
|
|
533 }
|
|
534 }
|
|
535 }
|
|
536 }
|
|
537 }
|
|
538
|
|
539 void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
|
|
540 {
|
|
541 int h;
|
|
542 for (h = 0; h < 2; h++)
|
|
543 {
|
|
544 s32 nb = nds.cycles + (h ? (99 * 12) : (256 * 12));
|
|
545
|
|
546 while (nb > nds.ARM9Cycle && !NDS_ARM9.waitIRQ)
|
|
547 nds.ARM9Cycle += armcpu_exec(&NDS_ARM9) << (cpu_clockdown_level_arm9);
|
|
548 if (NDS_ARM9.waitIRQ) nds.ARM9Cycle = nb;
|
|
549 while (nb > nds.ARM7Cycle && !NDS_ARM7.waitIRQ)
|
|
550 nds.ARM7Cycle += armcpu_exec(&NDS_ARM7) << (1 + (cpu_clockdown_level_arm7));
|
|
551 if (NDS_ARM7.waitIRQ) nds.ARM7Cycle = nb;
|
|
552 nds.cycles = (nds.ARM9Cycle<nds.ARM7Cycle)?nds.ARM9Cycle : nds.ARM7Cycle;
|
|
553
|
|
554 /* HBLANK */
|
|
555 if (h)
|
|
556 {
|
|
557 T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 2);
|
|
558 T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2);
|
|
559 NDS_ARM9HBlankInt();
|
|
560 NDS_ARM7HBlankInt();
|
|
561
|
|
562 if(nds.VCount<192)
|
|
563 {
|
|
564 if(MMU.DMAStartTime[0][0] == 2)
|
|
565 MMU_doDMA(0, 0);
|
|
566 if(MMU.DMAStartTime[0][1] == 2)
|
|
567 MMU_doDMA(0, 1);
|
|
568 if(MMU.DMAStartTime[0][2] == 2)
|
|
569 MMU_doDMA(0, 2);
|
|
570 if(MMU.DMAStartTime[0][3] == 2)
|
|
571 MMU_doDMA(0, 3);
|
|
572 }
|
|
573 }
|
|
574 else
|
|
575 {
|
|
576 /* HDISP */
|
|
577 u32 vmatch;
|
|
578
|
|
579 nds.nextHBlank += 4260;
|
|
580 ++nds.VCount;
|
|
581 T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFD);
|
|
582 T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFD);
|
|
583
|
|
584 if(MMU.DMAStartTime[0][0] == 3)
|
|
585 MMU_doDMA(0, 0);
|
|
586 if(MMU.DMAStartTime[0][1] == 3)
|
|
587 MMU_doDMA(0, 1);
|
|
588 if(MMU.DMAStartTime[0][2] == 3)
|
|
589 MMU_doDMA(0, 2);
|
|
590 if(MMU.DMAStartTime[0][3] == 3)
|
|
591 MMU_doDMA(0, 3);
|
|
592
|
|
593 // Main memory display
|
|
594 if(MMU.DMAStartTime[0][0] == 4)
|
|
595 {
|
|
596 MMU_doDMA(0, 0);
|
|
597 MMU.DMAStartTime[0][0] = 0;
|
|
598 }
|
|
599 if(MMU.DMAStartTime[0][1] == 4)
|
|
600 {
|
|
601 MMU_doDMA(0, 1);
|
|
602 MMU.DMAStartTime[0][1] = 0;
|
|
603 }
|
|
604 if(MMU.DMAStartTime[0][2] == 4)
|
|
605 {
|
|
606 MMU_doDMA(0, 2);
|
|
607 MMU.DMAStartTime[0][2] = 0;
|
|
608 }
|
|
609 if(MMU.DMAStartTime[0][3] == 4)
|
|
610 {
|
|
611 MMU_doDMA(0, 3);
|
|
612 MMU.DMAStartTime[0][3] = 0;
|
|
613 }
|
|
614
|
|
615 if(MMU.DMAStartTime[1][0] == 4)
|
|
616 {
|
|
617 MMU_doDMA(1, 0);
|
|
618 MMU.DMAStartTime[1][0] = 0;
|
|
619 }
|
|
620 if(MMU.DMAStartTime[1][1] == 4)
|
|
621 {
|
|
622 MMU_doDMA(1, 1);
|
|
623 MMU.DMAStartTime[0][1] = 0;
|
|
624 }
|
|
625 if(MMU.DMAStartTime[1][2] == 4)
|
|
626 {
|
|
627 MMU_doDMA(1, 2);
|
|
628 MMU.DMAStartTime[1][2] = 0;
|
|
629 }
|
|
630 if(MMU.DMAStartTime[1][3] == 4)
|
|
631 {
|
|
632 MMU_doDMA(1, 3);
|
|
633 MMU.DMAStartTime[1][3] = 0;
|
|
634 }
|
|
635
|
|
636 if(nds.VCount == 192)
|
|
637 {
|
|
638 /* VBLANK */
|
|
639 T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 1);
|
|
640 T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
|
|
641 NDS_ARM9VBlankInt();
|
|
642 NDS_ARM7VBlankInt();
|
|
643
|
|
644 if(MMU.DMAStartTime[0][0] == 1)
|
|
645 MMU_doDMA(0, 0);
|
|
646 if(MMU.DMAStartTime[0][1] == 1)
|
|
647 MMU_doDMA(0, 1);
|
|
648 if(MMU.DMAStartTime[0][2] == 1)
|
|
649 MMU_doDMA(0, 2);
|
|
650 if(MMU.DMAStartTime[0][3] == 1)
|
|
651 MMU_doDMA(0, 3);
|
|
652
|
|
653 if(MMU.DMAStartTime[1][0] == 1)
|
|
654 MMU_doDMA(1, 0);
|
|
655 if(MMU.DMAStartTime[1][1] == 1)
|
|
656 MMU_doDMA(1, 1);
|
|
657 if(MMU.DMAStartTime[1][2] == 1)
|
|
658 MMU_doDMA(1, 2);
|
|
659 if(MMU.DMAStartTime[1][3] == 1)
|
|
660 MMU_doDMA(1, 3);
|
|
661 }
|
|
662 else if(nds.VCount == 263)
|
|
663 {
|
|
664 const int cycles_per_frame = (263 * (99 * 12 + 256 * 12));
|
|
665 /* VDISP */
|
|
666 nds.nextHBlank = 3168;
|
|
667 nds.VCount = 0;
|
|
668 T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFE);
|
|
669 T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE);
|
|
670
|
|
671 nds.cycles -= cycles_per_frame;
|
|
672 nds.ARM9Cycle -= cycles_per_frame;
|
|
673 nds.ARM7Cycle -= cycles_per_frame;
|
|
674 nb -= cycles_per_frame;
|
|
675 if(MMU.timerON[0][0])
|
|
676 nds.timerCycle[0][0] -= cycles_per_frame;
|
|
677 if(MMU.timerON[0][1])
|
|
678 nds.timerCycle[0][1] -= cycles_per_frame;
|
|
679 if(MMU.timerON[0][2])
|
|
680 nds.timerCycle[0][2] -= cycles_per_frame;
|
|
681 if(MMU.timerON[0][3])
|
|
682 nds.timerCycle[0][3] -= cycles_per_frame;
|
|
683
|
|
684 if(MMU.timerON[1][0])
|
|
685 nds.timerCycle[1][0] -= cycles_per_frame;
|
|
686 if(MMU.timerON[1][1])
|
|
687 nds.timerCycle[1][1] -= cycles_per_frame;
|
|
688 if(MMU.timerON[1][2])
|
|
689 nds.timerCycle[1][2] -= cycles_per_frame;
|
|
690 if(MMU.timerON[1][3])
|
|
691 nds.timerCycle[1][3] -= cycles_per_frame;
|
|
692 if(MMU.DMAing[0][0])
|
|
693 MMU.DMACycle[0][0] -= cycles_per_frame;
|
|
694 if(MMU.DMAing[0][1])
|
|
695 MMU.DMACycle[0][1] -= cycles_per_frame;
|
|
696 if(MMU.DMAing[0][2])
|
|
697 MMU.DMACycle[0][2] -= cycles_per_frame;
|
|
698 if(MMU.DMAing[0][3])
|
|
699 MMU.DMACycle[0][3] -= cycles_per_frame;
|
|
700 if(MMU.DMAing[1][0])
|
|
701 MMU.DMACycle[1][0] -= cycles_per_frame;
|
|
702 if(MMU.DMAing[1][1])
|
|
703 MMU.DMACycle[1][1] -= cycles_per_frame;
|
|
704 if(MMU.DMAing[1][2])
|
|
705 MMU.DMACycle[1][2] -= cycles_per_frame;
|
|
706 if(MMU.DMAing[1][3])
|
|
707 MMU.DMACycle[1][3] -= cycles_per_frame;
|
|
708
|
|
709 }
|
|
710
|
|
711 T1WriteWord(ARM9Mem.ARM9_REG, 6, nds.VCount);
|
|
712 T1WriteWord(MMU.ARM7_REG, 6, nds.VCount);
|
|
713
|
|
714 vmatch = T1ReadWord(ARM9Mem.ARM9_REG, 4);
|
|
715 if((nds.VCount==(vmatch>>8)|((vmatch<<1)&(1<<8))))
|
|
716 {
|
|
717 T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 4);
|
|
718 if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 32)
|
|
719 NDS_makeARM9Int(2);
|
|
720 }
|
|
721 else
|
|
722 T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFB);
|
|
723
|
|
724 vmatch = T1ReadWord(MMU.ARM7_REG, 4);
|
|
725 if((nds.VCount==(vmatch>>8)|((vmatch<<1)&(1<<8))))
|
|
726 {
|
|
727 T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4);
|
|
728 if(T1ReadWord(MMU.ARM7_REG, 4) & 32)
|
|
729 NDS_makeARM7Int(2);
|
|
730 }
|
|
731 else
|
|
732 T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB);
|
|
733
|
|
734 timer_check();
|
|
735 dma_check();
|
|
736 }
|
|
737 }
|
|
738 }
|
|
739
|
|
740 void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
|
|
741 {
|
|
742 int v;
|
|
743 for (v = 0; v < 263; v++)
|
|
744 {
|
|
745 NDS_exec_hframe(cpu_clockdown_level_arm9, cpu_clockdown_level_arm7);
|
|
746 }
|
|
747 }
|
|
748
|