1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz, R. Belmont
3 /***************************************************************************
4
5 nds.cpp
6
7 Preliminary driver for first-generation Nintendo DS.
8
9 Tech info: http://problemkaputt.de/gbatek.htm
10
11 Notes:
12 Timers and DMAs 0-3 are ARM9's, 4-7 are ARM7's.
13 Interrupt registers [0] is ARM9, [1] is ARM7.
14
15 ***************************************************************************/
16
17 #include "emu.h"
18 #include "includes/nds.h"
19
20 #define VERBOSE_LEVEL (0)
21
22 // Measured value from GBATEK. Actual crystal unknown.
23 #define MASTER_CLOCK (33513982)
24
25 #define INT_VBL 0x00000001
26 #define INT_HBL 0x00000002
27 #define INT_VCNT 0x00000004
28 #define INT_TM0_OVERFLOW 0x00000008
29 #define INT_TM1_OVERFLOW 0x00000010
30 #define INT_TM2_OVERFLOW 0x00000020
31 #define INT_TM3_OVERFLOW 0x00000040
32 #define INT_SIO 0x00000080 // also RCNT/RTC (arm7 only)
33 #define INT_DMA0 0x00000100
34 #define INT_DMA1 0x00000200
35 #define INT_DMA2 0x00000400
36 #define INT_DMA3 0x00000800
37 #define INT_KEYPAD 0x00001000
38 #define INT_GAMEPAK 0x00002000 // GBA slot IRQ line (never used?)
39 #define INT_NA1 0x00004000 // unused
40 #define INT_NA2 0x00008000 // unused
41 #define INT_IPCSYNC 0x00010000
42 #define INT_IPCSENDEMPTY 0x00020000
43 #define INT_IPCRECVNOTEMPTY 0x00040000
44 #define INT_CARDXFERCOMPLETE 0x00080000
45 #define INT_CARDIREQ 0x00100000
46 #define INT_GEOCMDFIFO 0x00200000 // arm9 only
47 #define INT_SCREENUNFOLD 0x00400000 // arm7 only
48 #define INT_SPIBUS 0x00800000 // arm7 only
49 #define INT_WIFI 0x01000000 // arm7 only - also DSP on DSi
50 #define INT_CAMERA 0x02000000 // DSi only
51 #define INT_NA3 0x04000000
52 #define INT_NA4 0x08000000
53 #define INT_NEWDMA0 0x10000000 // DSi only
54 #define INT_NEWDMA1 0x20000000 // DSi only
55 #define INT_NEWDMA2 0x40000000 // DSi only
56 #define INT_NEWDMA3 0x80000000 // DSi only
57
58 static const uint32_t timer_clks[4] = { MASTER_CLOCK, MASTER_CLOCK / 64, MASTER_CLOCK / 256, MASTER_CLOCK / 1024 };
59
verboselog(device_t & device,int n_level,const char * s_fmt,...)60 static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, const char *s_fmt, ...)
61 {
62 if( VERBOSE_LEVEL >= n_level )
63 {
64 va_list v;
65 char buf[ 32768 ];
66 va_start( v, s_fmt );
67 vsprintf( buf, s_fmt, v );
68 va_end( v );
69 device.logerror( "%08x: %s", device.machine().describe_context(), buf );
70 }
71 }
72
arm7_io_r(offs_t offset,uint32_t mem_mask)73 uint32_t nds_state::arm7_io_r(offs_t offset, uint32_t mem_mask)
74 {
75 uint8_t temp1, temp2;
76 switch(offset)
77 {
78 case TIMER_OFFSET:
79 case TIMER_OFFSET+1:
80 case TIMER_OFFSET+2:
81 case TIMER_OFFSET+3:
82 {
83 uint32_t elapsed;
84 double time, ticks;
85 int timer = (offset - TIMER_OFFSET) + 4;
86
87 printf("Read timer reg %x (PC=%x)\n", timer, m_arm7->pc());
88
89 // update times for
90 if (m_timer_regs[timer] & 0x800000)
91 {
92 if (m_timer_regs[timer] & 0x00040000)
93 {
94 elapsed = m_timer_regs[timer] & 0xffff;
95 }
96 else
97 {
98 time = 0.1; //m_tmr_timer[timer]->elapsed().as_double();
99
100 ticks = (double)(0x10000 - (m_timer_regs[timer] & 0xffff));
101
102 // printf("time %f ticks %f 1/hz %f\n", time, ticks, 1.0 / m_timer_hz[timer]);
103
104 time *= ticks;
105 time /= (1.0 / m_timer_hz[timer]);
106
107 elapsed = (uint32_t)time;
108 }
109
110 // printf("elapsed = %x\n", elapsed);
111 }
112 else
113 {
114 // printf("Reading inactive timer!\n");
115 elapsed = 0;
116 }
117
118 return (m_timer_regs[timer] & 0xffff0000) | (elapsed & 0xffff);
119 }
120 break;
121
122 case IME_OFFSET:
123 return m_ime[1];
124
125 case IE_OFFSET:
126 return m_ie[1];
127
128 case IF_OFFSET:
129 return m_if[1];
130
131 case IPCSYNC_OFFSET:
132 return m_arm7_ipcsync;
133
134 case AUX_SPI_CNT_OFFSET:
135 printf("arm7: read AUX_SPI_CNT mask %08x\n", mem_mask);
136 return 0;
137 break;
138
139 case GAMECARD_BUS_CTRL_OFFSET:
140 //printf("arm7: read GAMECARD_BUS_CTRL (%08x) mask %08x\n", m_gamecard_ctrl, mem_mask);
141 return m_gamecard_ctrl;
142 break;
143
144 case GAMECARD_DATA_OFFSET:
145 printf("arm7: read to GAMECARD_DATA mask %08x\n", mem_mask);
146 return 0xffffffff;
147 break;
148
149 case GAMECARD_DATA_2_OFFSET:
150 printf("arm7: read to GAMECARD_DATA2 mask %08x\n", mem_mask);
151 return 0xffffffff;
152 break;
153
154 case GAMECARD_DATA_IN_OFFSET:
155 //printf("arm7: read to GAMECARD_DATA_IN mask %08x (len = %x)\n", mem_mask, m_cartdata_len);
156 if (m_cartdata_len >= 4)
157 {
158 m_cartdata_len -= 4;
159 }
160 else
161 {
162 m_cartdata_len = 0;
163 }
164
165 if (m_cartdata_len == 0)
166 {
167 printf("NDS: xfer over\n");
168 m_gamecard_ctrl &= ~GAMECARD_DATA_READY;
169 m_gamecard_ctrl &= ~GAMECARD_BLOCK_BUSY;
170 }
171 return 0xffffffff;
172 break;
173
174 case SPI_CTRL_OFFSET:
175 //printf("arm7: read SPI_CTRL mask %08x\n", mem_mask);
176 return 0;
177 break;
178
179 case POSTFLG_OFFSET:
180 /* Bit Use
181 * 0 0=Booting, 1=Booted (set by BIOS/firmware)
182 */
183 return m_arm7_postflg;
184
185 case WRAMSTAT_OFFSET:
186 temp1 = (((m_vramcntc & 3) == 2) && (m_vramcntc & 0x80)) ? 1 : 0;
187 temp2 = (((m_vramcntd & 3) == 2) && (m_vramcntd & 0x80)) ? 2 : 0;
188 return (m_wramcnt << 8) | temp1 | temp2;
189
190 default:
191 verboselog(*this, 0, "[ARM7] [IO] Unknown read: %08x (%08x)\n", offset*4, mem_mask);
192 break;
193 }
194
195 return 0;
196 }
197
arm7_io_w(offs_t offset,uint32_t data,uint32_t mem_mask)198 void nds_state::arm7_io_w(offs_t offset, uint32_t data, uint32_t mem_mask)
199 {
200 switch(offset)
201 {
202 case TIMER_OFFSET:
203 case TIMER_OFFSET+1:
204 case TIMER_OFFSET+2:
205 case TIMER_OFFSET+3:
206 {
207 double rate, clocksel;
208 uint32_t old_timer_regs;
209
210 int timer = (offset - TIMER_OFFSET)+4;
211
212 old_timer_regs = m_timer_regs[timer];
213
214 m_timer_regs[timer] = (m_timer_regs[timer] & ~(mem_mask & 0xFFFF0000)) | (data & (mem_mask & 0xFFFF0000));
215
216 printf("%08x to timer %d (mask %08x PC %x)\n", data, timer, ~mem_mask, m_arm7->pc());
217
218 if (ACCESSING_BITS_0_15)
219 {
220 m_timer_reload[timer] = ((m_timer_reload[timer] & ~mem_mask) | (data & mem_mask)) & 0x0000FFFF;
221 m_timer_recalc[timer] = 1;
222 }
223
224 // enabling this timer?
225 if ((ACCESSING_BITS_16_31) && (data & 0x800000))
226 {
227 double final;
228
229 if ((old_timer_regs & 0x00800000) == 0) // start bit 0 -> 1
230 {
231 m_timer_regs[timer] = (m_timer_regs[timer] & 0xFFFF0000) | (m_timer_reload[timer] & 0x0000FFFF);
232 }
233
234 rate = 0x10000 - (m_timer_regs[timer] & 0xffff);
235
236 clocksel = timer_clks[(m_timer_regs[timer] >> 16) & 3];
237
238 final = clocksel / rate;
239
240 m_timer_hz[timer] = final;
241
242 m_timer_recalc[timer] = 0;
243
244 printf("Enabling timer %d @ %f Hz regs %08x\n", timer, final, m_timer_regs[timer]);
245
246 // enable the timer
247 if( !(data & 0x40000) ) // if we're not in Count-Up mode
248 {
249 attotime time = attotime::from_hz(final);
250 m_tmr_timer[timer]->adjust(time, timer, time);
251 }
252 }
253 }
254 break;
255
256 case IME_OFFSET:
257 printf("ARM7: %08x to IME\n", data);
258 COMBINE_DATA(&m_ime[1]);
259 break;
260
261 case IE_OFFSET:
262 printf("ARM7: %08x to IE\n", data);
263 COMBINE_DATA(&m_ie[1]);
264 break;
265
266 case IF_OFFSET:
267 COMBINE_DATA(&m_if[1]);
268 break;
269
270 case IPCSYNC_OFFSET:
271 //printf("ARM7: %x to IPCSYNC\n", data);
272 m_arm9_ipcsync &= ~0xf;
273 m_arm9_ipcsync |= ((data >> 8) & 0xf);
274 m_arm7_ipcsync &= 0xf;
275 m_arm7_ipcsync |= (data & ~0xf);
276 break;
277
278 case AUX_SPI_CNT_OFFSET:
279 //printf("arm7: %08x to AUX_SPI_CNT mask %08x\n", data, mem_mask);
280 m_spicnt &= 0x0080;
281 m_spicnt |= (data & 0xe043);
282
283 break;
284
285 case GAMECARD_BUS_CTRL_OFFSET:
286 //printf("arm7: %08x to GAMECARD_BUS_CTRL mask %08x\n", data, mem_mask);
287 m_gamecard_ctrl &= GAMECARD_DATA_READY;
288 m_gamecard_ctrl |= (data & ~GAMECARD_DATA_READY);
289
290 if (!(m_spicnt & (1<<15)))
291 {
292 return;
293 }
294
295 if (!(m_gamecard_ctrl & GAMECARD_BLOCK_BUSY))
296 {
297 return;
298 }
299
300 m_cartdata_len = (m_gamecard_ctrl >> 24) & 7;
301 if (m_cartdata_len == 7)
302 {
303 m_cartdata_len = 4;
304 }
305 else if (m_cartdata_len != 0)
306 {
307 m_cartdata_len = 256 << m_cartdata_len;
308 }
309 printf("nds: cartdata for transfer = %x\n", m_cartdata_len);
310
311 if (m_cartdata_len > 0)
312 {
313 m_gamecard_ctrl |= GAMECARD_DATA_READY;
314 }
315 else
316 {
317 printf("NDS: xfer over\n");
318 m_gamecard_ctrl &= ~GAMECARD_DATA_READY;
319 m_gamecard_ctrl &= ~GAMECARD_BLOCK_BUSY;
320 }
321 break;
322
323 case GAMECARD_DATA_OFFSET:
324 //printf("arm7: %08x to GAMECARD_DATA mask %08x\n", data, mem_mask);
325 break;
326
327 case GAMECARD_DATA_2_OFFSET:
328 //printf("arm7: %08x to GAMECARD_DATA2 mask %08x\n", data, mem_mask);
329 break;
330
331 case SPI_CTRL_OFFSET:
332 //printf("arm7: %08x to SPI_CTRL mask %08x\n", data, mem_mask);
333 break;
334
335 case POSTFLG_OFFSET:
336 /* Bit Use
337 * 0 0=Booting, 1=Booted (set by BIOS/firmware)
338 */
339 if (!(m_arm7_postflg & POSTFLG_PBF_MASK) && m_arm7->pc() < 0x4000)
340 {
341 m_arm7_postflg &= ~POSTFLG_PBF_MASK;
342 m_arm7_postflg |= data & POSTFLG_PBF_MASK;
343 }
344
345 if (ACCESSING_BITS_8_15)
346 {
347 if ((data>>8) & 0x80)
348 {
349 printf("arm7: HALT\n"); // halts the arm7 until an interrupt occurs
350 m_arm7->suspend(SUSPEND_REASON_HALT, 1);
351 m_arm7halted = true;
352 }
353 }
354 break;
355 default:
356 verboselog(*this, 0, "[ARM7] [IO] Unknown write: %08x = %08x (%08x)\n", offset*4, data, mem_mask);
357 break;
358 }
359 }
360
arm9_io_r(offs_t offset,uint32_t mem_mask)361 uint32_t nds_state::arm9_io_r(offs_t offset, uint32_t mem_mask)
362 {
363 switch(offset)
364 {
365 case TIMER_OFFSET:
366 case TIMER_OFFSET+1:
367 case TIMER_OFFSET+2:
368 case TIMER_OFFSET+3:
369 {
370 uint32_t elapsed;
371 double time, ticks;
372 int timer = (offset - TIMER_OFFSET);
373
374 //printf("Read timer reg %x (PC=%x)\n", timer, m_arm9->pc());
375
376 // update times for
377 if (m_timer_regs[timer] & 0x800000)
378 {
379 if (m_timer_regs[timer] & 0x00040000)
380 {
381 elapsed = m_timer_regs[timer] & 0xffff;
382 }
383 else
384 {
385 time = 0.1; //m_tmr_timer[timer]->elapsed().as_double();
386
387 ticks = (double)(0x10000 - (m_timer_regs[timer] & 0xffff));
388
389 // printf("time %f ticks %f 1/hz %f\n", time, ticks, 1.0 / m_timer_hz[timer]);
390
391 time *= ticks;
392 time /= (1.0 / m_timer_hz[timer]);
393
394 elapsed = (uint32_t)time;
395 }
396
397 // printf("elapsed = %x\n", elapsed);
398 }
399 else
400 {
401 // printf("Reading inactive timer!\n");
402 elapsed = 0;
403 }
404
405 return (m_timer_regs[timer] & 0xffff0000) | (elapsed & 0xffff);
406 }
407 break;
408
409 case IME_OFFSET:
410 return m_ime[0];
411
412 case IE_OFFSET:
413 return m_ie[0];
414
415 case IF_OFFSET:
416 return m_if[0];
417
418 case IPCSYNC_OFFSET:
419 return m_arm9_ipcsync;
420
421 case POSTFLG_OFFSET:
422 /* Bit Use
423 * 0 0=Booting, 1=Booted (set by BIOS/firmware)
424 * 1 RAM
425 */
426 return m_arm9_postflg;
427 default:
428 verboselog(*this, 0, "[ARM9] [IO] Unknown read: %08x (%08x)\n", offset*4, mem_mask);
429 break;
430 }
431
432 return 0;
433 }
434
arm9_io_w(offs_t offset,uint32_t data,uint32_t mem_mask)435 void nds_state::arm9_io_w(offs_t offset, uint32_t data, uint32_t mem_mask)
436 {
437 switch(offset)
438 {
439 case TIMER_OFFSET:
440 case TIMER_OFFSET+1:
441 case TIMER_OFFSET+2:
442 case TIMER_OFFSET+3:
443 {
444 double rate, clocksel;
445 uint32_t old_timer_regs;
446
447 int timer = (offset - TIMER_OFFSET)+4;
448
449 old_timer_regs = m_timer_regs[timer];
450
451 m_timer_regs[timer] = (m_timer_regs[timer] & ~(mem_mask & 0xFFFF0000)) | (data & (mem_mask & 0xFFFF0000));
452
453 printf("%x to timer %d (mask %x PC %x)\n", data, timer, ~mem_mask, m_arm9->pc());
454
455 if (ACCESSING_BITS_0_15)
456 {
457 m_timer_reload[timer] = ((m_timer_reload[timer] & ~mem_mask) | (data & mem_mask)) & 0x0000FFFF;
458 m_timer_recalc[timer] = 1;
459 }
460
461 // enabling this timer?
462 if ((ACCESSING_BITS_16_31) && (data & 0x800000))
463 {
464 double final;
465
466 if ((old_timer_regs & 0x00800000) == 0) // start bit 0 -> 1
467 {
468 m_timer_regs[timer] = (m_timer_regs[timer] & 0xFFFF0000) | (m_timer_reload[timer] & 0x0000FFFF);
469 }
470
471 rate = 0x10000 - (m_timer_regs[timer] & 0xffff);
472
473 clocksel = timer_clks[(m_timer_regs[timer] >> 16) & 3];
474
475 final = clocksel / rate;
476
477 m_timer_hz[timer] = final;
478
479 m_timer_recalc[timer] = 0;
480
481 printf("Enabling timer %d @ %f Hz\n", timer, final);
482
483 // enable the timer
484 if( !(data & 0x40000) ) // if we're not in Count-Up mode
485 {
486 attotime time = attotime::from_hz(final);
487 m_tmr_timer[timer]->adjust(time, timer, time);
488 }
489 }
490 }
491 break;
492
493 case IME_OFFSET:
494 printf("ARM9: %08x to IME\n", data);
495 COMBINE_DATA(&m_ime[0]);
496 break;
497
498 case IE_OFFSET:
499 printf("ARM9: %08x to IE\n", data);
500 COMBINE_DATA(&m_ie[0]);
501 break;
502
503 case IF_OFFSET:
504 COMBINE_DATA(&m_if[0]);
505 break;
506
507 case IPCSYNC_OFFSET:
508 printf("ARM9: %x to IPCSYNC\n", data);
509 m_arm7_ipcsync &= ~0xf;
510 m_arm7_ipcsync |= ((data >> 8) & 0xf);
511 m_arm9_ipcsync &= 0xf;
512 m_arm9_ipcsync |= (data & ~0xf);
513 break;
514
515 case VRAMCNT_A_OFFSET:
516 if (ACCESSING_BITS_0_7) // VRAMCNT_A
517 {
518 m_vramcnta = data & 0xff;
519 }
520 if (ACCESSING_BITS_8_15) // VRAMCNT_B
521 {
522 m_vramcntb = (data >> 8) & 0xff;
523 }
524 if (ACCESSING_BITS_16_23) // VRAMCNT_C
525 {
526 m_vramcntc = (data >> 16) & 0xff;
527 }
528 if (ACCESSING_BITS_24_31) // VRAMCNT_D
529 {
530 m_vramcntd = (data >> 24) & 0xff;
531 }
532 break;
533
534 case WRAMCNT_OFFSET:
535 if (ACCESSING_BITS_0_7) // VRAMCNT_E
536 {
537 m_vramcnte = data & 0xff;
538 }
539 if (ACCESSING_BITS_8_15) // VRAMCNT_F
540 {
541 m_vramcntf = (data >> 8) & 0xff;
542 }
543 if (ACCESSING_BITS_16_23) // VRAMCNT_G
544 {
545 m_vramcntg = (data >> 16) & 0xff;
546 }
547 if (ACCESSING_BITS_24_31) // WRAMCNT
548 {
549 m_wramcnt = (data>>24) & 0x3;
550 m_arm7wrambnk->set_bank(m_wramcnt);
551 m_arm9wrambnk->set_bank(m_wramcnt);
552 }
553 break;
554
555 case VRAMCNT_H_OFFSET:
556 if (ACCESSING_BITS_0_7) // VRAMCNT_H
557 {
558 m_vramcnth = data & 0xff;
559 }
560 if (ACCESSING_BITS_8_15) // VRAMCNT_I
561 {
562 m_vramcnti = (data >> 8) & 0xff;
563 }
564 break;
565
566 case POSTFLG_OFFSET:
567 /* Bit Use
568 * 0 0=Booting, 1=Booted (set by BIOS/firmware)
569 * 1 RAM
570 */
571 if (!(m_arm9_postflg & POSTFLG_PBF_MASK))
572 {
573 m_arm9_postflg &= ~POSTFLG_PBF_MASK;
574 m_arm9_postflg |= data & POSTFLG_PBF_MASK;
575 }
576 m_arm9_postflg &= ~POSTFLG_RAM_MASK;
577 m_arm9_postflg |= data & POSTFLG_RAM_MASK;
578 break;
579 default:
580 verboselog(*this, 0, "[ARM7] [IO] Unknown write: %08x = %08x (%08x)\n", offset*4, data, mem_mask);
581 break;
582 }
583 }
584
nds_arm7_map(address_map & map)585 void nds_state::nds_arm7_map(address_map &map)
586 {
587 map(0x00000000, 0x00003fff).rom().region("arm7", 0);
588 map(0x02000000, 0x023fffff).ram().mirror(0x00400000).share("mainram");
589 map(0x03000000, 0x03007fff).mirror(0x007f8000).m(m_arm7wrambnk, FUNC(address_map_bank_device::amap32));
590 map(0x03800000, 0x0380ffff).ram().mirror(0x007f0000).share("arm7ram");
591 map(0x04000000, 0x0410ffff).rw(FUNC(nds_state::arm7_io_r), FUNC(nds_state::arm7_io_w));
592 }
593
nds_arm9_map(address_map & map)594 void nds_state::nds_arm9_map(address_map &map)
595 {
596 map(0x02000000, 0x023fffff).ram().mirror(0x00400000).share("mainram");
597 map(0x03000000, 0x03007fff).mirror(0x00ff8000).m("nds9wram", FUNC(address_map_bank_device::amap32));
598 map(0x04000000, 0x0410ffff).rw(FUNC(nds_state::arm9_io_r), FUNC(nds_state::arm9_io_w));
599 map(0xffff0000, 0xffff0fff).rom().mirror(0x1000).region("arm9", 0);
600 }
601
602 // ARM7 views of WRAM
nds7_wram_map(address_map & map)603 void nds_state::nds7_wram_map(address_map &map)
604 {
605 map(0x00000, 0x07fff).rw(FUNC(nds_state::wram_arm7mirror_r), FUNC(nds_state::wram_arm7mirror_w));
606 map(0x08000, 0x0bfff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w));
607 map(0x0c000, 0x0ffff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w));
608 map(0x10000, 0x13fff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w));
609 map(0x14000, 0x17fff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w));
610 map(0x18000, 0x1ffff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w));
611 }
612
613 // ARM9 views of WRAM
nds9_wram_map(address_map & map)614 void nds_state::nds9_wram_map(address_map &map)
615 {
616 map(0x00000, 0x07fff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w));
617 map(0x08000, 0x0bfff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w));
618 map(0x0c000, 0x0ffff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w));
619 map(0x10000, 0x13fff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w));
620 map(0x14000, 0x17fff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w));
621 map(0x18000, 0x1ffff).noprw().nopw(); // probably actually open bus? GBATEK describes as "random"
622 }
623
wram_first_half_r(offs_t offset)624 uint32_t nds_state::wram_first_half_r(offs_t offset) { return m_WRAM[offset]; }
wram_second_half_r(offs_t offset)625 uint32_t nds_state::wram_second_half_r(offs_t offset) { return m_WRAM[offset+0x4000]; }
wram_first_half_w(offs_t offset,uint32_t data,uint32_t mem_mask)626 void nds_state::wram_first_half_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_WRAM[offset]); }
wram_second_half_w(offs_t offset,uint32_t data,uint32_t mem_mask)627 void nds_state::wram_second_half_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_WRAM[offset+0x4000]); }
wram_arm7mirror_r(offs_t offset)628 uint32_t nds_state::wram_arm7mirror_r(offs_t offset) { return m_arm7ram[offset]; }
wram_arm7mirror_w(offs_t offset,uint32_t data,uint32_t mem_mask)629 void nds_state::wram_arm7mirror_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_arm7ram[offset]); }
630
INPUT_PORTS_START(nds)631 static INPUT_PORTS_START( nds )
632 INPUT_PORTS_END
633
634 void nds_state::machine_reset()
635 {
636 m_arm7_postflg = 0;
637 m_arm9_postflg = 0;
638 m_wramcnt = 0;
639 m_arm7wrambnk->set_bank(0);
640 m_arm9wrambnk->set_bank(0);
641 m_arm7halted = false;
642 }
643
machine_start()644 void nds_state::machine_start()
645 {
646 int i;
647
648 for (i = 0; i < 8; i++)
649 {
650 m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nds_state::dma_complete),this));
651 m_dma_timer[i]->adjust(attotime::never, i);
652
653 m_tmr_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nds_state::timer_expire),this));
654 m_tmr_timer[i]->adjust(attotime::never, i);
655 }
656
657 m_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nds_state::handle_irq),this));
658 m_irq_timer->adjust(attotime::never);
659 }
660
TIMER_CALLBACK_MEMBER(nds_state::dma_complete)661 TIMER_CALLBACK_MEMBER(nds_state::dma_complete)
662 {
663 #if 0
664 static const uint32_t ch_int[8] = { INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3, INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3 };
665
666 uintptr_t ch = param;
667
668 // printf("dma complete: ch %d\n", ch);
669
670 m_dma_timer[ch]->adjust(attotime::never);
671
672 int ctrl = DMACNT_H(ch);
673
674 // IRQ
675 if (ctrl & 0x4000)
676 {
677 request_irq(ch_int[ch]);
678 }
679
680 // if we're supposed to repeat, don't clear "active" and then the next vbl/hbl will retrigger us
681 // always clear active for immediate DMAs though
682 if (!((ctrl>>9) & 1) || ((ctrl & 0x3000) == 0))
683 {
684 DMACNT_H_RESET(ch, 0x8000); // clear "active" bit
685 }
686 else
687 {
688 // if repeat, reload the count
689 if ((ctrl>>9) & 1)
690 {
691 m_dma_cnt[ch] = DMACNT_L(ch);
692
693 // if increment & reload mode, reload the destination
694 if (((ctrl>>5)&3) == 3)
695 {
696 m_dma_dst[ch] = DMADAD(ch);
697 }
698 }
699 }
700 #endif
701 }
702
dma_exec(int ch)703 void nds_state::dma_exec(int ch)
704 {
705 #if 0
706 address_space &space;
707 uint32_t src = m_dma_src[ch];
708 uint32_t dst = m_dma_dst[ch];
709 uint16_t ctrl = DMACNT_H(ch);
710 int srcadd = (ctrl >> 7) & 3;
711 int dstadd = (ctrl >> 5) & 3;
712
713 if (ch > 4)
714 {
715 space = m_arm7->space(AS_PROGRAM);
716 }
717 else
718 {
719 space = m_arm9->space(AS_PROGRAM);
720 }
721
722 int cnt = m_dma_cnt[ch];
723 if (cnt == 0)
724 {
725 if (ch == 3)
726 cnt = 0x10000;
727 else
728 cnt = 0x4000;
729 }
730
731 // if (dst >= 0x6000000 && dst <= 0x6017fff)
732 // printf("DMA exec: ch %d from %08x to %08x, mode %04x, count %04x (%s)\n", (int)ch, src, dst, ctrl, cnt, ((ctrl>>10) & 1) ? "32" : "16");
733
734 for (int i = 0; i < cnt; i++)
735 {
736 if ((ctrl>>10) & 1)
737 {
738 src &= 0xfffffffc;
739 dst &= 0xfffffffc;
740
741 // 32-bit
742 space.write_dword(dst, space.read_dword(src));
743 switch (dstadd)
744 {
745 case 0: // increment
746 dst += 4;
747 break;
748 case 1: // decrement
749 dst -= 4;
750 break;
751 case 2: // don't move
752 break;
753 case 3: // increment and reload
754 dst += 4;
755 break;
756 }
757 switch (srcadd)
758 {
759 case 0: // increment
760 src += 4;
761 break;
762 case 1: // decrement
763 src -= 4;
764 break;
765 case 2: // don't move
766 break;
767 case 3: // not used ("Metal Max 2 Kai" expects no increment/decrement)
768 break;
769 }
770 }
771 else
772 {
773 src &= 0xfffffffe;
774 dst &= 0xfffffffe;
775
776 // 16-bit
777 space.write_word(dst, space.read_word(src));
778 switch (dstadd)
779 {
780 case 0: // increment
781 dst += 2;
782 break;
783 case 1: // decrement
784 dst -= 2;
785 break;
786 case 2: // don't move
787 break;
788 case 3: // increment and reload
789 dst += 2;
790 break;
791 }
792 switch (srcadd)
793 {
794 case 0: // increment
795 src += 2;
796 break;
797 case 1: // decrement
798 src -= 2;
799 break;
800 case 2: // don't move
801 break;
802 case 3: // not used (see note in 32-bit version above)
803 break;
804 }
805 }
806 }
807
808 m_dma_src[ch] = src;
809 m_dma_dst[ch] = dst;
810 #endif
811 // printf("settng DMA timer %d for %d cycs (tmr %x)\n", ch, cnt, (uint32_t)m_dma_timer[ch]);
812 // m_dma_timer[ch]->adjust(ATTOTIME_IN_CYCLES(0, cnt), ch);
813 dma_complete(nullptr, ch);
814 }
815
TIMER_CALLBACK_MEMBER(nds_state::handle_irq)816 TIMER_CALLBACK_MEMBER(nds_state::handle_irq)
817 {
818 request_irq(0, m_if[0]);
819 request_irq(1, m_if[1]);
820
821 m_irq_timer->adjust(attotime::never);
822 }
823
request_irq(int cpu,uint32_t int_type)824 void nds_state::request_irq(int cpu, uint32_t int_type)
825 {
826 // set flag for later recovery
827 m_if[cpu] |= int_type;
828
829 printf("request IRQ %08x on CPU %d\n", int_type, cpu);
830
831 // is this specific interrupt enabled?
832 int_type &= m_ie[cpu];
833 if (int_type != 0)
834 {
835 // master enable?
836 if (m_ime[cpu] & 1)
837 {
838 if (cpu == 0)
839 {
840 m_arm9->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE);
841 m_arm9->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE);
842 }
843 else
844 {
845 if (m_arm7halted)
846 {
847 printf("ARM7 unhalting\n");
848 m_arm7->resume(SUSPEND_REASON_HALT);
849 m_arm7halted = false;
850 }
851
852 m_arm7->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE);
853 m_arm7->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE);
854 }
855 }
856 }
857 }
858
TIMER_CALLBACK_MEMBER(nds_state::timer_expire)859 TIMER_CALLBACK_MEMBER(nds_state::timer_expire)
860 {
861 static const uint32_t tmr_ints[8] = { INT_TM0_OVERFLOW, INT_TM1_OVERFLOW, INT_TM2_OVERFLOW, INT_TM3_OVERFLOW };
862 uintptr_t tmr = (uintptr_t) param;
863 int cpu = (tmr > 4) ? 1 : 0;
864
865 verboselog(*this, 1, "Timer %d expired\n", (int)tmr);
866
867 // "The reload value is copied into the counter only upon following two situations: Automatically upon timer overflows,"
868 // "or when the timer start bit becomes changed from 0 to 1."
869 if (m_timer_recalc[tmr] != 0)
870 {
871 double rate, clocksel, final;
872 attotime time;
873 m_timer_recalc[tmr] = 0;
874 m_timer_regs[tmr] = (m_timer_regs[tmr] & 0xFFFF0000) | (m_timer_reload[tmr] & 0x0000FFFF);
875 rate = 0x10000 - (m_timer_regs[tmr] & 0xffff);
876 clocksel = timer_clks[(m_timer_regs[tmr] >> 16) & 3];
877 final = clocksel / rate;
878 m_timer_hz[tmr] = final;
879 time = attotime::from_hz(final);
880 m_tmr_timer[tmr]->adjust(time, tmr, time);
881 }
882
883 // Handle count-up timing
884 switch (tmr)
885 {
886 case 0:
887 if (m_timer_regs[1] & 0x40000)
888 {
889 m_timer_regs[1] = (( ( m_timer_regs[1] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[1] & 0xffff0000);
890 if( ( m_timer_regs[1] & 0x0000ffff ) == 0 )
891 {
892 m_timer_regs[1] |= m_timer_reload[1];
893 if( ( m_timer_regs[1] & 0x400000 ) && ( m_ime[cpu] != 0 ) )
894 {
895 request_irq(cpu, tmr_ints[1]);
896 }
897 if( ( m_timer_regs[2] & 0x40000 ) )
898 {
899 m_timer_regs[2] = (( ( m_timer_regs[2] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[2] & 0xffff0000);
900 if( ( m_timer_regs[2] & 0x0000ffff ) == 0 )
901 {
902 m_timer_regs[2] |= m_timer_reload[2];
903 if( ( m_timer_regs[2] & 0x400000 ) && ( m_ime[cpu] != 0 ) )
904 {
905 request_irq(cpu, tmr_ints[2]);
906 }
907 if( ( m_timer_regs[3] & 0x40000 ) )
908 {
909 m_timer_regs[3] = (( ( m_timer_regs[3] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[3] & 0xffff0000);
910 if( ( m_timer_regs[3] & 0x0000ffff ) == 0 )
911 {
912 m_timer_regs[3] |= m_timer_reload[3];
913 if( ( m_timer_regs[3] & 0x400000 ) && ( m_ime[cpu] != 0 ) )
914 {
915 request_irq(cpu, tmr_ints[3]);
916 }
917 }
918 }
919 }
920 }
921 }
922 }
923 break;
924 case 1:
925 if (m_timer_regs[2] & 0x40000)
926 {
927 m_timer_regs[2] = (( ( m_timer_regs[2] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[2] & 0xffff0000);
928 if( ( m_timer_regs[2] & 0x0000ffff ) == 0 )
929 {
930 m_timer_regs[2] |= m_timer_reload[2];
931 if( ( m_timer_regs[2] & 0x400000 ) && ( m_ime[cpu] != 0 ) )
932 {
933 request_irq(cpu, tmr_ints[2]);
934 }
935 if( ( m_timer_regs[3] & 0x40000 ) )
936 {
937 m_timer_regs[3] = (( ( m_timer_regs[3] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[3] & 0xffff0000);
938 if( ( m_timer_regs[3] & 0x0000ffff ) == 0 )
939 {
940 m_timer_regs[3] |= m_timer_reload[3];
941 if( ( m_timer_regs[3] & 0x400000 ) && ( m_ime[cpu] != 0 ) )
942 {
943 request_irq(cpu, tmr_ints[3]);
944 }
945 }
946 }
947 }
948 }
949 break;
950 case 2:
951 if (m_timer_regs[3] & 0x40000)
952 {
953 m_timer_regs[3] = (( ( m_timer_regs[3] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[3] & 0xffff0000);
954 if( ( m_timer_regs[3] & 0x0000ffff ) == 0 )
955 {
956 m_timer_regs[3] |= m_timer_reload[3];
957 if( ( m_timer_regs[3] & 0x400000 ) && ( m_ime[cpu] != 0 ) )
958 {
959 request_irq(cpu, tmr_ints[3]);
960 }
961 }
962 }
963 break;
964 }
965
966 // are we supposed to IRQ?
967 if ((m_timer_regs[tmr] & 0x400000) && (m_ime[cpu] != 0))
968 {
969 request_irq(cpu, tmr_ints[tmr & 3]);
970 }
971 }
972
nds(machine_config & config)973 void nds_state::nds(machine_config &config)
974 {
975 ARM7(config, m_arm7, MASTER_CLOCK);
976 m_arm7->set_addrmap(AS_PROGRAM, &nds_state::nds_arm7_map);
977
978 ARM946ES(config, m_arm9, MASTER_CLOCK*2);
979 m_arm9->set_high_vectors();
980 m_arm9->set_addrmap(AS_PROGRAM, &nds_state::nds_arm9_map);
981
982 // WRAM
983 ADDRESS_MAP_BANK(config, "nds7wram").set_map(&nds_state::nds7_wram_map).set_options(ENDIANNESS_LITTLE, 32, 32, 0x8000);
984 ADDRESS_MAP_BANK(config, "nds9wram").set_map(&nds_state::nds9_wram_map).set_options(ENDIANNESS_LITTLE, 32, 32, 0x8000);
985 }
986
987 /* Help identifying the region and revisions of the set would be greatly appreciated! */
988 ROM_START( nds )
989 ROM_REGION( 0x1000, "arm9", 0 )
990 ROM_LOAD( "biosnds9.rom", 0x0000, 0x1000, CRC(2ab23573) SHA1(bfaac75f101c135e32e2aaf541de6b1be4c8c62d) )
991
992 ROM_REGION( 0x4000, "arm7", 0 )
993 ROM_LOAD( "biosnds7.rom", 0x0000, 0x4000, CRC(1280f0d5) SHA1(24f67bdea115a2c847c8813a262502ee1607b7df) )
994
995 ROM_REGION32_LE( 0x40000, "firmware", 0 )
996 ROM_LOAD( "firmware.bin", 0x0000, 0x40000, CRC(945f9dc9) SHA1(cfe072921ee3fb93f688743f8beef89043c3e9ad) )
997 ROM_END
998
999 // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
1000 CONS( 2004, nds, 0, 0, nds, nds, nds_state, empty_init, "Nintendo", "DS", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
1001