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