1 /*****************************************************************************
2 
3     h6280.c - Portable HuC6280 emulator
4 
5     Copyright Bryan McPhail, mish@tendril.co.uk
6 
7     This source code is based (with permission!) on the 6502 emulator by
8     Juergen Buchmueller.  It is released as part of the Mame emulator project.
9     Let me know if you intend to use this code in any other project.
10 
11 
12     NOTICE:
13 
14     This code is around 99% complete!  Several things are unimplemented,
15     some due to lack of time, some due to lack of documentation, mainly
16     due to lack of programs using these features.
17 
18     csh, csl opcodes are not supported.
19 
20     I am unsure if flag B is set upon execution of rti.
21 
22     Cycle counts should be quite accurate.
23 
24 
25     Changelog, version 1.02:
26         JMP + indirect X (0x7c) opcode fixed.
27         SMB + RMB opcodes fixed in disassembler.
28         change_pc function calls removed.
29         TSB & TRB now set flags properly.
30         BIT opcode altered.
31 
32     Changelog, version 1.03:
33         Swapped IRQ mask for IRQ1 & IRQ2 (thanks Yasuhiro)
34 
35     Changelog, version 1.04, 28/9/99-22/10/99:
36         Adjusted RTI (thanks Karl)
37         TST opcodes fixed in disassembler (missing break statements in a case!).
38         TST behaviour fixed.
39         SMB/RMB/BBS/BBR fixed in disassembler.
40 
41     Changelog, version 1.05, 8/12/99-16/12/99:
42         Added CAB's timer implementation (note: irq ack & timer reload are changed).
43         Fixed STA IDX.
44         Fixed B flag setting on BRK.
45         Assumed CSH & CSL to take 2 cycles each.
46 
47         Todo:  Performance could be improved by precalculating timer fire position.
48 
49     Changelog, version 1.06, 4/5/00 - last opcode bug found?
50         JMP indirect was doing a EAL++; instead of EAD++; - Obviously causing
51         a corrupt read when L = 0xff!  This fixes Bloody Wolf and Trio The Punch!
52 
53     Changelog, version 1.07, 3/9/00:
54         Changed timer to be single shot - fixes Crude Buster music in level 1.
55 
56     Changelog, version 1.08, 8/11/05: (Charles MacDonald)
57 
58         Changed timer implementation, no longer single shot and reading the
59         timer registers returns the count only. Fixes the following:
60         - Mesopotamia: Music tempo & in-game timer
61         - Dragon Saber: DDA effects
62         - Magical Chase: Music tempo and speed regulation
63         - Cadash: Allows the first level to start
64         - Turrican: Allows the game to start
65 
66         Changed PLX and PLY to set NZ flags. Fixes:
67         - Afterburner: Graphics unpacking
68         - Aoi Blink: Collision detection with background
69 
70         Fixed the decimal version of ADC/SBC to *not* update the V flag,
71         only the binary ones do.
72 
73         Fixed B flag handling so it is always set outside of an interrupt;
74         even after being set by PLP and RTI.
75 
76         Fixed P state after reset to set I and B, leaving T, D cleared and
77         NVZC randomized (cleared in this case).
78 
79         Fixed interrupt processing order (Timer has highest priority followed
80         by IRQ1 and finally IRQ2).
81 
82     Changelog, version 1.09, 1/07/06: (Rob Bohms)
83 
84         Added emulation of the T flag, fixes PCE Ankuku Densetsu title screen
85 
86     Changelog, version 1.10, 5/09/07: (Wilbert Pol)
87 
88         - Taking of interrupts is delayed to respect a pending instruction already
89           in the instruction pipeline; fixes After Burner.
90         - Added 1 cycle for decimal mode ADC and SBC instructions.
91         - Changed cycle counts for CSH and CSL instructions to 3.
92         - Added T flag support to the SBC instruction.
93         - Fixed ADC T flag to set the Z flag based on the value read.
94         - Added 3 cycle penalty to ADC, AND, EOR, ORA, and SBC instructions
95           when the T flag is set.
96         - Fixed cycle count and support for 65536 byte blocks for the TAI, TDD,
97           TIA, TII, and TIN instructions.
98         - Fixed RDWORD macro in the disassembler.
99         - Fixed setting of N and V flags in the TST instructions.
100         - Removed unneeded debug_mmr code.
101         - Fixed TSB and TRB instructions.
102         - Added 1 delay when accessing the VDC or VCE areas.
103         - Implemented low and high speed cpu modes.
104 
105     Changelog, version 1.11, 18/09/07: (Wilbert Pol)
106 
107         - Improvements to the handling of taking of delayed interrupts.
108 
109 ******************************************************************************/
110 //#include "debugger.h"
111 //#include "deprecat.h"
112 #include "burnint.h"
113 #include "h6280.h"
114 #include "h6280_intf.h"
115 //#include "driver.h"
116 
117 #define offs_t	unsigned int
118 #define change_pc(x) PCW = (x)
119 
120 #define CLEAR_LINE	0
121 #define ASSERT_LINE	1
122 #define INPUT_LINE_NMI	0x20
123 
124 #define H6280_INLINE static
125 
126 extern INT32 nh6280CpuActive;
127 
128 static int 	h6280_ICount = 0;
129 //static unsigned int h6280_totalcycles = 0;
130 
131 static h6280_Regs  h6280;
132 
133 void h6280_set_irq_line(INT32 irqline, INT32 state);
134 #define set_irq_line h6280_set_irq_line
135 
136 /* include the macros */
137 #include "h6280ops.h"
138 
139 /* include the opcode macros, functions and function pointer tables */
140 #include "tblh6280.c"
141 
142 #if 0
143 /*****************************************************************************/
144 static void h6280_init(int index, int clock, const void *config, int (*irqcallback)(int))
145 {
146 	state_save_register_item("h6280", index, h6280.ppc.w.l);
147 	state_save_register_item("h6280", index, h6280.pc.w.l);
148 	state_save_register_item("h6280", index, h6280.sp.w.l);
149 	state_save_register_item("h6280", index, h6280.zp.w.l);
150 	state_save_register_item("h6280", index, h6280.ea.w.l);
151 	state_save_register_item("h6280", index, h6280.a);
152 	state_save_register_item("h6280", index, h6280.x);
153 	state_save_register_item("h6280", index, h6280.y);
154 	state_save_register_item("h6280", index, h6280.p);
155 	state_save_register_item_array("h6280", index, h6280.mmr);
156 	state_save_register_item("h6280", index, h6280.irq_mask);
157 	state_save_register_item("h6280", index, h6280.timer_status);
158 	state_save_register_item("h6280", index, h6280.timer_ack);
159 	state_save_register_item("h6280", index, h6280.clocks_per_cycle);
160 	state_save_register_item("h6280", index, h6280.timer_value);
161 	state_save_register_item("h6280", index, h6280.timer_load);
162 	state_save_register_item("h6280", index, h6280.nmi_state);
163 	state_save_register_item("h6280", index, h6280.irq_state[0]);
164 	state_save_register_item("h6280", index, h6280.irq_state[1]);
165 	state_save_register_item("h6280", index, h6280.irq_state[2]);
166 	state_save_register_item("h6280", index, h6280.irq_pending);
167 
168 	#if LAZY_FLAGS
169 	state_save_register_item("h6280", index, h6280.NZ);
170 	#endif
171 	state_save_register_item("h6280", index, h6280.io_buffer);
172 
173 	h6280.irq_callback = irqcallback;
174 }
175 #endif
176 
h6280_irqcallback(int (* irqcallback)(int))177 void h6280_irqcallback(int (*irqcallback)(int))
178 {
179 	h6280.irq_callback = irqcallback;
180 }
181 
h6280Reset(void)182 void h6280Reset(void)
183 {
184 #if defined FBNEO_DEBUG
185 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280Reset called without init\n"));
186 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280Reset called with no CPU open\n"));
187 #endif
188 
189 	/* wipe out the h6280 structure */
190 	int (*save_irqcallback)(int) = h6280.irq_callback;
191 	memset(&h6280, 0, sizeof(h6280_Regs));
192 	h6280.irq_callback = save_irqcallback;
193 
194 	/* set I and B flags */
195 	P = _fI | _fB;
196 
197     /* stack starts at 0x01ff */
198 	h6280.sp.d = 0x1ff;
199 
200     /* read the reset vector into PC */
201 	PCL = RDMEM(H6280_RESET_VEC);
202 	PCH = RDMEM((H6280_RESET_VEC+1));
203 	CHANGE_PC;
204 
205 	/* CPU starts in low speed mode */
206     h6280.clocks_per_cycle = 4;
207 
208 	/* timer off by default */
209 	h6280.timer_status=0;
210 	h6280.timer_load = 128 * 1024;
211 
212     /* clear pending interrupts */
213 	for (INT32 i = 0; i < 3; i++)
214 		h6280.irq_state[i] = CLEAR_LINE;
215 	h6280.nmi_state = CLEAR_LINE;
216 
217 	h6280.irq_pending = 0;
218 
219 	h6280.h6280_totalcycles = 0;
220 }
221 
222 #if 0
223 static void h6280_exit(void)
224 {
225 	/* nothing */
226 }
227 #endif
228 
229 static int end_run = 0;
230 
h6280Run(int cycles)231 int h6280Run(int cycles)
232 {
233 #if defined FBNEO_DEBUG
234 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280Run called without init\n"));
235 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280Run called with no CPU open\n"));
236 #endif
237 
238 	int in;
239 	h6280_ICount = cycles;
240 	h6280.h6280_iCycles = cycles;
241 
242 	end_run = 0;
243 
244 	if ( h6280.irq_pending == 2 ) {
245 		h6280.irq_pending--;
246 	}
247 
248 	/* Execute instructions */
249 	do
250     {
251     	if ((h6280.ppc.w.l ^ h6280.pc.w.l) & 0xe000)
252     		CHANGE_PC;
253 		h6280.ppc = h6280.pc;
254 
255 //		debugger_instruction_hook(Machine, PCW);
256 
257 		/* Execute 1 instruction */
258 		in=RDOP();
259 		PCW++;
260 		insnh6280[in]();
261 
262 		if ( h6280.irq_pending ) {
263 			if ( h6280.irq_pending == 1 ) {
264 				if ( !(P & _fI) ) {
265 					h6280.irq_pending--;
266 					CHECK_AND_TAKE_IRQ_LINES;
267 				}
268 			} else {
269 				h6280.irq_pending--;
270 			}
271 		}
272 
273 		/* Check internal timer */
274 		if(h6280.timer_status)
275 		{
276 			if(h6280.timer_value<=0)
277 			{
278 				if ( ! h6280.irq_pending )
279 					h6280.irq_pending = 1;
280 				while( h6280.timer_value <= 0 )
281 					h6280.timer_value += h6280.timer_load;
282 				set_irq_line(2,ASSERT_LINE);
283 			}
284 		}
285 	} while (h6280_ICount > 0 && !end_run);
286 
287 	cycles = cycles - h6280_ICount;
288 
289 	h6280.h6280_totalcycles += cycles;
290 	h6280_ICount = 0;
291 	h6280.h6280_iCycles = 0;
292 
293 	return cycles;
294 }
295 
h6280_get_context(void * dst)296 void h6280_get_context(void *dst)
297 {
298 	if( dst )
299 		*(h6280_Regs*)dst = h6280;
300 }
301 
h6280_set_context(void * src)302 void h6280_set_context(void *src)
303 {
304 	if( src )
305 		h6280 = *(h6280_Regs*)src;
306 	CHANGE_PC;
307 }
308 
h6280TotalCycles()309 int h6280TotalCycles()
310 {
311 #if defined FBNEO_DEBUG
312 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280TotalCycles called without init\n"));
313 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280TotalCycles called with no CPU open\n"));
314 #endif
315 
316 	return h6280.h6280_totalcycles + (h6280.h6280_iCycles - h6280_ICount);
317 }
318 
h6280RunEnd()319 void h6280RunEnd()
320 {
321 #if defined FBNEO_DEBUG
322 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280RunEnd called without init\n"));
323 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280RunEnd called with no CPU open\n"));
324 #endif
325 
326 	end_run = 1;
327 }
328 
h6280Idle(INT32 cycles)329 INT32 h6280Idle(INT32 cycles)
330 {
331 #if defined FBNEO_DEBUG
332 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280Idle called without init\n"));
333 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280Idle called with no CPU open\n"));
334 #endif
335 
336 	h6280.h6280_totalcycles += cycles;
337 
338 	return cycles;
339 }
340 
341 /*****************************************************************************/
342 
h6280_set_irq_line(int irqline,int state)343 void h6280_set_irq_line(int irqline, int state)
344 {
345 #if defined FBNEO_DEBUG
346 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_set_irq_line called without init\n"));
347 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_set_irq_line called with no CPU open\n"));
348 #endif
349 
350 	if (irqline == INPUT_LINE_NMI)
351 	{
352 		if ( state != ASSERT_LINE ) return;
353 		h6280.nmi_state = state;
354 		CHECK_IRQ_LINES;
355 	}
356 	else if (irqline < 3)
357 	{
358 		if (state == CPU_IRQSTATUS_HOLD) {
359 			state = CPU_IRQSTATUS_ACK;
360 			h6280.irq_hold = 1;
361 		}
362 		/* If the state has not changed, just return */
363 		if ( h6280.irq_state[irqline] == state )
364 			return;
365 
366 	    h6280.irq_state[irqline] = state;
367 
368 		CHECK_IRQ_LINES;
369 	}
370 }
371 
372 
373 
374 /*****************************************************************************/
375 
h6280_irq_status_r(unsigned int offset)376 unsigned char h6280_irq_status_r(unsigned int offset)
377 {
378 #if defined FBNEO_DEBUG
379 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_irq_status_r called without init\n"));
380 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_irq_status_r called with no CPU open\n"));
381 #endif
382 
383 	int status;
384 
385 	switch (offset&3)
386 	{
387 	default:return h6280.io_buffer;break;
388 	case 3:
389 		{
390 			status=0;
391 			if(h6280.irq_state[1]!=CLEAR_LINE) status|=1; /* IRQ 2 */
392 			if(h6280.irq_state[0]!=CLEAR_LINE) status|=2; /* IRQ 1 */
393 			if(h6280.irq_state[2]!=CLEAR_LINE) status|=4; /* TIMER */
394 			return status|(h6280.io_buffer&(~H6280_IRQ_MASK));
395 		}
396 	case 2: return h6280.irq_mask|(h6280.io_buffer&(~H6280_IRQ_MASK));break;
397 	}
398 }
399 
h6280_irq_status_w(unsigned int offset,unsigned char data)400 void h6280_irq_status_w(unsigned int offset, unsigned char data)
401 {
402 #if defined FBNEO_DEBUG
403 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_irq_status_w called without init\n"));
404 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_irq_status_w called with no CPU open\n"));
405 #endif
406 
407 	h6280.io_buffer=data;
408 	switch (offset&3)
409 	{
410 		default:h6280.io_buffer=data;break;
411 		case 2: /* Write irq mask */
412 			h6280.irq_mask=data&0x7;
413 			CHECK_IRQ_LINES;
414 			break;
415 
416 		case 3: /* Timer irq ack */
417 			set_irq_line(2,CLEAR_LINE);
418 			break;
419 	}
420 }
421 
h6280_timer_r(unsigned int)422 unsigned char h6280_timer_r(unsigned int)
423 {
424 #if defined FBNEO_DEBUG
425 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_timer_r called without init\n"));
426 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_timer_r called with no CPU open\n"));
427 #endif
428 
429 	/* only returns countdown */
430 	return ((h6280.timer_value>>10)&0x7F)|(h6280.io_buffer&0x80);
431 }
432 
h6280_timer_w(unsigned int offset,unsigned char data)433 void h6280_timer_w(unsigned int offset, unsigned char data)
434 {
435 #if defined FBNEO_DEBUG
436 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_timer_w called without init\n"));
437 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_timer_w called with no CPU open\n"));
438 #endif
439 
440 	h6280.io_buffer=data;
441 	switch (offset&1) {
442 		case 0: /* Counter preload */
443 			h6280.timer_load=((data&127)+1)*1024;
444 			return;
445 
446 		case 1: /* Counter enable */
447 			if(data&1)
448 			{	/* stop -> start causes reload */
449 				if(h6280.timer_status==0) h6280.timer_value=h6280.timer_load;
450 			}
451 			h6280.timer_status=data&1;
452 			return;
453 	}
454 }
455 
456 #if 0
457 static int h6280_translate(int space, int intention, offs_t *addr)
458 {
459 #if 0
460 	if (space == ADDRESS_SPACE_PROGRAM)
461 		*addr = TRANSLATED(*addr);
462 	return TRUE;
463 #else
464 	if (space == 0)
465 		*addr = TRANSLATED(*addr);
466 	return 1;
467 #endif
468 }
469 #endif
470 
h6280io_get_buffer()471 UINT8 h6280io_get_buffer()
472 {
473 	return h6280.io_buffer;
474 }
h6280io_set_buffer(UINT8 data)475 void h6280io_set_buffer(UINT8 data)
476 {
477 	h6280.io_buffer=data;
478 }
479 
480 #if 0
481 /*****************************************************************************/
482 
483 /**************************************************************************
484  * Generic set_info
485  **************************************************************************/
486 
487 static void h6280_set_info(UINT32 state, cpuinfo *info)
488 {
489 	switch (state)
490 	{
491 		/* --- the following bits of info are set as 64-bit signed integers --- */
492 		case CPUINFO_INT_INPUT_STATE + 0:			set_irq_line(0, info->i);					break;
493 		case CPUINFO_INT_INPUT_STATE + 1:			set_irq_line(1, info->i);					break;
494 		case CPUINFO_INT_INPUT_STATE + 2:			set_irq_line(2, info->i);					break;
495 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:set_irq_line(INPUT_LINE_NMI, info->i);	break;
496 
497 		case CPUINFO_INT_PC:
498 		case CPUINFO_INT_REGISTER + H6280_PC:		PCW = info->i;								break;
499 		case CPUINFO_INT_SP:
500 		case CPUINFO_INT_REGISTER + H6280_S:		S = info->i;								break;
501 		case CPUINFO_INT_REGISTER + H6280_P:		P = info->i;								break;
502 		case CPUINFO_INT_REGISTER + H6280_A:		A = info->i;								break;
503 		case CPUINFO_INT_REGISTER + H6280_X:		X = info->i;								break;
504 		case CPUINFO_INT_REGISTER + H6280_Y:		Y = info->i;								break;
505 		case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: h6280.irq_mask = info->i; CHECK_IRQ_LINES;	break;
506 		case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: h6280.timer_status = info->i; 			break;
507 		case CPUINFO_INT_REGISTER + H6280_NMI_STATE: set_irq_line( INPUT_LINE_NMI, info->i ); 	break;
508 		case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: set_irq_line( 0, info->i ); 				break;
509 		case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: set_irq_line( 1, info->i ); 				break;
510 		case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: set_irq_line( 2, info->i ); 				break;
511 		case CPUINFO_INT_REGISTER + H6280_M1:		h6280.mmr[0] = info->i;						break;
512 		case CPUINFO_INT_REGISTER + H6280_M2:		h6280.mmr[1] = info->i;						break;
513 		case CPUINFO_INT_REGISTER + H6280_M3:		h6280.mmr[2] = info->i;						break;
514 		case CPUINFO_INT_REGISTER + H6280_M4:		h6280.mmr[3] = info->i;						break;
515 		case CPUINFO_INT_REGISTER + H6280_M5:		h6280.mmr[4] = info->i;						break;
516 		case CPUINFO_INT_REGISTER + H6280_M6:		h6280.mmr[5] = info->i;						break;
517 		case CPUINFO_INT_REGISTER + H6280_M7:		h6280.mmr[6] = info->i;						break;
518 		case CPUINFO_INT_REGISTER + H6280_M8:		h6280.mmr[7] = info->i;						break;
519 	}
520 }
521 
522 
523 
524 /**************************************************************************
525  * Generic get_info
526  **************************************************************************/
527 
528 void h6280_get_info(UINT32 state, cpuinfo *info)
529 {
530 	switch (state)
531 	{
532 		/* --- the following bits of info are returned as 64-bit signed integers --- */
533 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(h6280);				break;
534 		case CPUINFO_INT_INPUT_LINES:					info->i = 3;							break;
535 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
536 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
537 		case CPUINFO_INT_CLOCK_MULTIPLIER:				info->i = 1;							break;
538 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
539 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
540 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 7;							break;
541 		case CPUINFO_INT_MIN_CYCLES:					info->i = 2;							break;
542 		case CPUINFO_INT_MAX_CYCLES:					info->i = 17 + 6*65536;					break;
543 
544 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
545 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 21;					break;
546 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
547 		case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16;					break;
548 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
549 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
550 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
551 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
552 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 2;					break;
553 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
554 
555 		case CPUINFO_INT_INPUT_STATE + 0:				info->i = h6280.irq_state[0];			break;
556 		case CPUINFO_INT_INPUT_STATE + 1:				info->i = h6280.irq_state[1];			break;
557 		case CPUINFO_INT_INPUT_STATE + 2:				info->i = h6280.irq_state[2];			break;
558 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	info->i = h6280.nmi_state; 				break;
559 
560 		case CPUINFO_INT_PREVIOUSPC:					info->i = h6280.ppc.d;					break;
561 
562 		case CPUINFO_INT_PC:
563 		case CPUINFO_INT_REGISTER + H6280_PC:			info->i = PCD;							break;
564 		case CPUINFO_INT_SP:
565 		case CPUINFO_INT_REGISTER + H6280_S:			info->i = S;							break;
566 		case CPUINFO_INT_REGISTER + H6280_P:			info->i = P;							break;
567 		case CPUINFO_INT_REGISTER + H6280_A:			info->i = A;							break;
568 		case CPUINFO_INT_REGISTER + H6280_X:			info->i = X;							break;
569 		case CPUINFO_INT_REGISTER + H6280_Y:			info->i = Y;							break;
570 		case CPUINFO_INT_REGISTER + H6280_IRQ_MASK:		info->i = h6280.irq_mask;				break;
571 		case CPUINFO_INT_REGISTER + H6280_TIMER_STATE:	info->i = h6280.timer_status;			break;
572 		case CPUINFO_INT_REGISTER + H6280_NMI_STATE:	info->i = h6280.nmi_state;				break;
573 		case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE:	info->i = h6280.irq_state[0];			break;
574 		case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE:	info->i = h6280.irq_state[1];			break;
575 		case CPUINFO_INT_REGISTER + H6280_IRQT_STATE:	info->i = h6280.irq_state[2];			break;
576 		case CPUINFO_INT_REGISTER + H6280_M1:			info->i = h6280.mmr[0];					break;
577 		case CPUINFO_INT_REGISTER + H6280_M2:			info->i = h6280.mmr[1];					break;
578 		case CPUINFO_INT_REGISTER + H6280_M3:			info->i = h6280.mmr[2];					break;
579 		case CPUINFO_INT_REGISTER + H6280_M4:			info->i = h6280.mmr[3];					break;
580 		case CPUINFO_INT_REGISTER + H6280_M5:			info->i = h6280.mmr[4];					break;
581 		case CPUINFO_INT_REGISTER + H6280_M6:			info->i = h6280.mmr[5];					break;
582 		case CPUINFO_INT_REGISTER + H6280_M7:			info->i = h6280.mmr[6];					break;
583 		case CPUINFO_INT_REGISTER + H6280_M8:			info->i = h6280.mmr[7];					break;
584 
585 		/* --- the following bits of info are returned as pointers to data or functions --- */
586 		case CPUINFO_PTR_SET_INFO:						info->setinfo = h6280_set_info;			break;
587 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = h6280_get_context;	break;
588 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = h6280_set_context;	break;
589 		case CPUINFO_PTR_INIT:							info->init = h6280_init;				break;
590 		case CPUINFO_PTR_RESET:							info->reset = h6280_reset;				break;
591 		case CPUINFO_PTR_EXIT:							info->exit = h6280_exit;				break;
592 		case CPUINFO_PTR_EXECUTE:						info->execute = h6280_execute;			break;
593 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
594 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = h6280_dasm;			break;
595 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &h6280_ICount;			break;
596 		case CPUINFO_PTR_TRANSLATE:						info->translate = h6280_translate;		break;
597 
598 		/* --- the following bits of info are returned as NULL-terminated strings --- */
599 		case CPUINFO_STR_NAME:							strcpy(info->s, "HuC6280");				break;
600 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "Hudsonsoft 6280");		break;
601 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "1.11");				break;
602 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
603 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "Copyright Bryan McPhail, mish@tendril.co.uk"); break;
604 
605 		case CPUINFO_STR_FLAGS:
606 			sprintf(info->s, "%c%c%c%c%c%c%c%c",
607 				h6280.p & 0x80 ? 'N':'.',
608 				h6280.p & 0x40 ? 'V':'.',
609 				h6280.p & 0x20 ? 'R':'.',
610 				h6280.p & 0x10 ? 'B':'.',
611 				h6280.p & 0x08 ? 'D':'.',
612 				h6280.p & 0x04 ? 'I':'.',
613 				h6280.p & 0x02 ? 'Z':'.',
614 				h6280.p & 0x01 ? 'C':'.');
615 			break;
616 
617 		case CPUINFO_STR_REGISTER + H6280_PC:			sprintf(info->s, "PC:%04X", h6280.pc.d); break;
618         case CPUINFO_STR_REGISTER + H6280_S:			sprintf(info->s, "S:%02X", h6280.sp.b.l); break;
619         case CPUINFO_STR_REGISTER + H6280_P:			sprintf(info->s, "P:%02X", h6280.p); break;
620         case CPUINFO_STR_REGISTER + H6280_A:			sprintf(info->s, "A:%02X", h6280.a); break;
621 		case CPUINFO_STR_REGISTER + H6280_X:			sprintf(info->s, "X:%02X", h6280.x); break;
622 		case CPUINFO_STR_REGISTER + H6280_Y:			sprintf(info->s, "Y:%02X", h6280.y); break;
623 		case CPUINFO_STR_REGISTER + H6280_IRQ_MASK:		sprintf(info->s, "IM:%02X", h6280.irq_mask); break;
624 		case CPUINFO_STR_REGISTER + H6280_TIMER_STATE:	sprintf(info->s, "TMR:%02X", h6280.timer_status); break;
625 		case CPUINFO_STR_REGISTER + H6280_NMI_STATE:	sprintf(info->s, "NMI:%X", h6280.nmi_state); break;
626 		case CPUINFO_STR_REGISTER + H6280_IRQ1_STATE:	sprintf(info->s, "IRQ1:%X", h6280.irq_state[0]); break;
627 		case CPUINFO_STR_REGISTER + H6280_IRQ2_STATE:	sprintf(info->s, "IRQ2:%X", h6280.irq_state[1]); break;
628 		case CPUINFO_STR_REGISTER + H6280_IRQT_STATE:	sprintf(info->s, "IRQT:%X", h6280.irq_state[2]); break;
629 		case CPUINFO_STR_REGISTER + H6280_M1:			sprintf(info->s, "M1:%02X", h6280.mmr[0]); break;
630 		case CPUINFO_STR_REGISTER + H6280_M2:			sprintf(info->s, "M2:%02X", h6280.mmr[1]); break;
631 		case CPUINFO_STR_REGISTER + H6280_M3:			sprintf(info->s, "M3:%02X", h6280.mmr[2]); break;
632 		case CPUINFO_STR_REGISTER + H6280_M4:			sprintf(info->s, "M4:%02X", h6280.mmr[3]); break;
633 		case CPUINFO_STR_REGISTER + H6280_M5:			sprintf(info->s, "M5:%02X", h6280.mmr[4]); break;
634 		case CPUINFO_STR_REGISTER + H6280_M6:			sprintf(info->s, "M6:%02X", h6280.mmr[5]); break;
635 		case CPUINFO_STR_REGISTER + H6280_M7:			sprintf(info->s, "M7:%02X", h6280.mmr[6]); break;
636 		case CPUINFO_STR_REGISTER + H6280_M8:			sprintf(info->s, "M8:%02X", h6280.mmr[7]); break;
637 	}
638 }
639 #endif
640