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 FBA_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 
h6280Run(int cycles)229 int h6280Run(int cycles)
230 {
231 #if defined FBA_DEBUG
232 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280Run called without init\n"));
233 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280Run called with no CPU open\n"));
234 #endif
235 
236 	int in;
237 	h6280_ICount = cycles;
238 	h6280.h6280_iCycles = cycles;
239 
240 	if ( h6280.irq_pending == 2 ) {
241 		h6280.irq_pending--;
242 	}
243 
244 	/* Execute instructions */
245 	do
246     {
247     	if ((h6280.ppc.w.l ^ h6280.pc.w.l) & 0xe000)
248     		CHANGE_PC;
249 		h6280.ppc = h6280.pc;
250 
251 //		debugger_instruction_hook(Machine, PCW);
252 
253 		/* Execute 1 instruction */
254 		in=RDOP();
255 		PCW++;
256 		insnh6280[in]();
257 
258 		if ( h6280.irq_pending ) {
259 			if ( h6280.irq_pending == 1 ) {
260 				if ( !(P & _fI) ) {
261 					h6280.irq_pending--;
262 					CHECK_AND_TAKE_IRQ_LINES;
263 				}
264 			} else {
265 				h6280.irq_pending--;
266 			}
267 		}
268 
269 		/* Check internal timer */
270 		if(h6280.timer_status)
271 		{
272 			if(h6280.timer_value<=0)
273 			{
274 				if ( ! h6280.irq_pending )
275 					h6280.irq_pending = 1;
276 				while( h6280.timer_value <= 0 )
277 					h6280.timer_value += h6280.timer_load;
278 				set_irq_line(2,ASSERT_LINE);
279 			}
280 		}
281 	} while (h6280_ICount > 0);
282 
283 	h6280.h6280_totalcycles += cycles - h6280_ICount;
284 	h6280_ICount = 0;
285 	h6280.h6280_iCycles = 0;
286 
287 	return cycles - h6280_ICount;
288 }
289 
h6280_get_context(void * dst)290 void h6280_get_context(void *dst)
291 {
292 	if( dst )
293 		*(h6280_Regs*)dst = h6280;
294 }
295 
h6280_set_context(void * src)296 void h6280_set_context(void *src)
297 {
298 	if( src )
299 		h6280 = *(h6280_Regs*)src;
300 	CHANGE_PC;
301 }
302 
h6280TotalCycles()303 int h6280TotalCycles()
304 {
305 #if defined FBA_DEBUG
306 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280TotalCycles called without init\n"));
307 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280TotalCycles called with no CPU open\n"));
308 #endif
309 
310 	return h6280.h6280_totalcycles + (h6280.h6280_iCycles - h6280_ICount);;
311 }
312 
h6280RunEnd()313 void h6280RunEnd()
314 {
315 #if defined FBA_DEBUG
316 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280RunEnd called without init\n"));
317 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280RunEnd called with no CPU open\n"));
318 #endif
319 
320 	h6280_ICount = 0;
321 }
322 
323 /*****************************************************************************/
324 
h6280_set_irq_line(int irqline,int state)325 void h6280_set_irq_line(int irqline, int state)
326 {
327 #if defined FBA_DEBUG
328 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_set_irq_line called without init\n"));
329 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_set_irq_line called with no CPU open\n"));
330 #endif
331 
332 	if (irqline == INPUT_LINE_NMI)
333 	{
334 		if ( state != ASSERT_LINE ) return;
335 		h6280.nmi_state = state;
336 		CHECK_IRQ_LINES;
337 	}
338 	else if (irqline < 3)
339 	{
340 		if (state == CPU_IRQSTATUS_HOLD) {
341 			state = CPU_IRQSTATUS_ACK;
342 			h6280.irq_hold = 1;
343 		}
344 		/* If the state has not changed, just return */
345 		if ( h6280.irq_state[irqline] == state )
346 			return;
347 
348 	    h6280.irq_state[irqline] = state;
349 
350 		CHECK_IRQ_LINES;
351 	}
352 }
353 
354 
355 
356 /*****************************************************************************/
357 
h6280_irq_status_r(unsigned int offset)358 unsigned char h6280_irq_status_r(unsigned int offset)
359 {
360 #if defined FBA_DEBUG
361 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_irq_status_r called without init\n"));
362 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_irq_status_r called with no CPU open\n"));
363 #endif
364 
365 	int status;
366 
367 	switch (offset&3)
368 	{
369 	default:return h6280.io_buffer;break;
370 	case 3:
371 		{
372 			status=0;
373 			if(h6280.irq_state[1]!=CLEAR_LINE) status|=1; /* IRQ 2 */
374 			if(h6280.irq_state[0]!=CLEAR_LINE) status|=2; /* IRQ 1 */
375 			if(h6280.irq_state[2]!=CLEAR_LINE) status|=4; /* TIMER */
376 			return status|(h6280.io_buffer&(~H6280_IRQ_MASK));
377 		}
378 	case 2: return h6280.irq_mask|(h6280.io_buffer&(~H6280_IRQ_MASK));break;
379 	}
380 }
381 
h6280_irq_status_w(unsigned int offset,unsigned char data)382 void h6280_irq_status_w(unsigned int offset, unsigned char data)
383 {
384 #if defined FBA_DEBUG
385 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_irq_status_w called without init\n"));
386 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_irq_status_w called with no CPU open\n"));
387 #endif
388 
389 	h6280.io_buffer=data;
390 	switch (offset&3)
391 	{
392 		default:h6280.io_buffer=data;break;
393 		case 2: /* Write irq mask */
394 			h6280.irq_mask=data&0x7;
395 			CHECK_IRQ_LINES;
396 			break;
397 
398 		case 3: /* Timer irq ack */
399 			set_irq_line(2,CLEAR_LINE);
400 			break;
401 	}
402 }
403 
h6280_timer_r(unsigned int)404 unsigned char h6280_timer_r(unsigned int)
405 {
406 #if defined FBA_DEBUG
407 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_timer_r called without init\n"));
408 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_timer_r called with no CPU open\n"));
409 #endif
410 
411 	/* only returns countdown */
412 	return ((h6280.timer_value>>10)&0x7F)|(h6280.io_buffer&0x80);
413 }
414 
h6280_timer_w(unsigned int offset,unsigned char data)415 void h6280_timer_w(unsigned int offset, unsigned char data)
416 {
417 #if defined FBA_DEBUG
418 	if (!DebugCPU_H6280Initted) bprintf(PRINT_ERROR, _T("h6280_timer_w called without init\n"));
419 	if (nh6280CpuActive == -1) bprintf(PRINT_ERROR, _T("h6280_timer_w called with no CPU open\n"));
420 #endif
421 
422 	h6280.io_buffer=data;
423 	switch (offset&1) {
424 		case 0: /* Counter preload */
425 			h6280.timer_load=h6280.timer_value=((data&127)+1)*1024;
426 			return;
427 
428 		case 1: /* Counter enable */
429 			if(data&1)
430 			{	/* stop -> start causes reload */
431 				if(h6280.timer_status==0) h6280.timer_value=h6280.timer_load;
432 			}
433 			h6280.timer_status=data&1;
434 			return;
435 	}
436 }
437 
438 #if 0
439 static int h6280_translate(int space, int intention, offs_t *addr)
440 {
441 #if 0
442 	if (space == ADDRESS_SPACE_PROGRAM)
443 		*addr = TRANSLATED(*addr);
444 	return TRUE;
445 #else
446 	if (space == 0)
447 		*addr = TRANSLATED(*addr);
448 	return 1;
449 #endif
450 }
451 #endif
452 
h6280io_get_buffer()453 UINT8 h6280io_get_buffer()
454 {
455 	return h6280.io_buffer;
456 }
h6280io_set_buffer(UINT8 data)457 void h6280io_set_buffer(UINT8 data)
458 {
459 	h6280.io_buffer=data;
460 }
461 
462 #if 0
463 /*****************************************************************************/
464 
465 /**************************************************************************
466  * Generic set_info
467  **************************************************************************/
468 
469 static void h6280_set_info(UINT32 state, cpuinfo *info)
470 {
471 	switch (state)
472 	{
473 		/* --- the following bits of info are set as 64-bit signed integers --- */
474 		case CPUINFO_INT_INPUT_STATE + 0:			set_irq_line(0, info->i);					break;
475 		case CPUINFO_INT_INPUT_STATE + 1:			set_irq_line(1, info->i);					break;
476 		case CPUINFO_INT_INPUT_STATE + 2:			set_irq_line(2, info->i);					break;
477 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:set_irq_line(INPUT_LINE_NMI, info->i);	break;
478 
479 		case CPUINFO_INT_PC:
480 		case CPUINFO_INT_REGISTER + H6280_PC:		PCW = info->i;								break;
481 		case CPUINFO_INT_SP:
482 		case CPUINFO_INT_REGISTER + H6280_S:		S = info->i;								break;
483 		case CPUINFO_INT_REGISTER + H6280_P:		P = info->i;								break;
484 		case CPUINFO_INT_REGISTER + H6280_A:		A = info->i;								break;
485 		case CPUINFO_INT_REGISTER + H6280_X:		X = info->i;								break;
486 		case CPUINFO_INT_REGISTER + H6280_Y:		Y = info->i;								break;
487 		case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: h6280.irq_mask = info->i; CHECK_IRQ_LINES;	break;
488 		case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: h6280.timer_status = info->i; 			break;
489 		case CPUINFO_INT_REGISTER + H6280_NMI_STATE: set_irq_line( INPUT_LINE_NMI, info->i ); 	break;
490 		case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: set_irq_line( 0, info->i ); 				break;
491 		case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: set_irq_line( 1, info->i ); 				break;
492 		case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: set_irq_line( 2, info->i ); 				break;
493 		case CPUINFO_INT_REGISTER + H6280_M1:		h6280.mmr[0] = info->i;						break;
494 		case CPUINFO_INT_REGISTER + H6280_M2:		h6280.mmr[1] = info->i;						break;
495 		case CPUINFO_INT_REGISTER + H6280_M3:		h6280.mmr[2] = info->i;						break;
496 		case CPUINFO_INT_REGISTER + H6280_M4:		h6280.mmr[3] = info->i;						break;
497 		case CPUINFO_INT_REGISTER + H6280_M5:		h6280.mmr[4] = info->i;						break;
498 		case CPUINFO_INT_REGISTER + H6280_M6:		h6280.mmr[5] = info->i;						break;
499 		case CPUINFO_INT_REGISTER + H6280_M7:		h6280.mmr[6] = info->i;						break;
500 		case CPUINFO_INT_REGISTER + H6280_M8:		h6280.mmr[7] = info->i;						break;
501 	}
502 }
503 
504 
505 
506 /**************************************************************************
507  * Generic get_info
508  **************************************************************************/
509 
510 void h6280_get_info(UINT32 state, cpuinfo *info)
511 {
512 	switch (state)
513 	{
514 		/* --- the following bits of info are returned as 64-bit signed integers --- */
515 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(h6280);				break;
516 		case CPUINFO_INT_INPUT_LINES:					info->i = 3;							break;
517 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
518 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
519 		case CPUINFO_INT_CLOCK_MULTIPLIER:				info->i = 1;							break;
520 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
521 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
522 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 7;							break;
523 		case CPUINFO_INT_MIN_CYCLES:					info->i = 2;							break;
524 		case CPUINFO_INT_MAX_CYCLES:					info->i = 17 + 6*65536;					break;
525 
526 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
527 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 21;					break;
528 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
529 		case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16;					break;
530 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
531 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
532 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
533 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
534 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 2;					break;
535 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
536 
537 		case CPUINFO_INT_INPUT_STATE + 0:				info->i = h6280.irq_state[0];			break;
538 		case CPUINFO_INT_INPUT_STATE + 1:				info->i = h6280.irq_state[1];			break;
539 		case CPUINFO_INT_INPUT_STATE + 2:				info->i = h6280.irq_state[2];			break;
540 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	info->i = h6280.nmi_state; 				break;
541 
542 		case CPUINFO_INT_PREVIOUSPC:					info->i = h6280.ppc.d;					break;
543 
544 		case CPUINFO_INT_PC:
545 		case CPUINFO_INT_REGISTER + H6280_PC:			info->i = PCD;							break;
546 		case CPUINFO_INT_SP:
547 		case CPUINFO_INT_REGISTER + H6280_S:			info->i = S;							break;
548 		case CPUINFO_INT_REGISTER + H6280_P:			info->i = P;							break;
549 		case CPUINFO_INT_REGISTER + H6280_A:			info->i = A;							break;
550 		case CPUINFO_INT_REGISTER + H6280_X:			info->i = X;							break;
551 		case CPUINFO_INT_REGISTER + H6280_Y:			info->i = Y;							break;
552 		case CPUINFO_INT_REGISTER + H6280_IRQ_MASK:		info->i = h6280.irq_mask;				break;
553 		case CPUINFO_INT_REGISTER + H6280_TIMER_STATE:	info->i = h6280.timer_status;			break;
554 		case CPUINFO_INT_REGISTER + H6280_NMI_STATE:	info->i = h6280.nmi_state;				break;
555 		case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE:	info->i = h6280.irq_state[0];			break;
556 		case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE:	info->i = h6280.irq_state[1];			break;
557 		case CPUINFO_INT_REGISTER + H6280_IRQT_STATE:	info->i = h6280.irq_state[2];			break;
558 		case CPUINFO_INT_REGISTER + H6280_M1:			info->i = h6280.mmr[0];					break;
559 		case CPUINFO_INT_REGISTER + H6280_M2:			info->i = h6280.mmr[1];					break;
560 		case CPUINFO_INT_REGISTER + H6280_M3:			info->i = h6280.mmr[2];					break;
561 		case CPUINFO_INT_REGISTER + H6280_M4:			info->i = h6280.mmr[3];					break;
562 		case CPUINFO_INT_REGISTER + H6280_M5:			info->i = h6280.mmr[4];					break;
563 		case CPUINFO_INT_REGISTER + H6280_M6:			info->i = h6280.mmr[5];					break;
564 		case CPUINFO_INT_REGISTER + H6280_M7:			info->i = h6280.mmr[6];					break;
565 		case CPUINFO_INT_REGISTER + H6280_M8:			info->i = h6280.mmr[7];					break;
566 
567 		/* --- the following bits of info are returned as pointers to data or functions --- */
568 		case CPUINFO_PTR_SET_INFO:						info->setinfo = h6280_set_info;			break;
569 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = h6280_get_context;	break;
570 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = h6280_set_context;	break;
571 		case CPUINFO_PTR_INIT:							info->init = h6280_init;				break;
572 		case CPUINFO_PTR_RESET:							info->reset = h6280_reset;				break;
573 		case CPUINFO_PTR_EXIT:							info->exit = h6280_exit;				break;
574 		case CPUINFO_PTR_EXECUTE:						info->execute = h6280_execute;			break;
575 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
576 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = h6280_dasm;			break;
577 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &h6280_ICount;			break;
578 		case CPUINFO_PTR_TRANSLATE:						info->translate = h6280_translate;		break;
579 
580 		/* --- the following bits of info are returned as NULL-terminated strings --- */
581 		case CPUINFO_STR_NAME:							strcpy(info->s, "HuC6280");				break;
582 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "Hudsonsoft 6280");		break;
583 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "1.11");				break;
584 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
585 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "Copyright Bryan McPhail, mish@tendril.co.uk"); break;
586 
587 		case CPUINFO_STR_FLAGS:
588 			sprintf(info->s, "%c%c%c%c%c%c%c%c",
589 				h6280.p & 0x80 ? 'N':'.',
590 				h6280.p & 0x40 ? 'V':'.',
591 				h6280.p & 0x20 ? 'R':'.',
592 				h6280.p & 0x10 ? 'B':'.',
593 				h6280.p & 0x08 ? 'D':'.',
594 				h6280.p & 0x04 ? 'I':'.',
595 				h6280.p & 0x02 ? 'Z':'.',
596 				h6280.p & 0x01 ? 'C':'.');
597 			break;
598 
599 		case CPUINFO_STR_REGISTER + H6280_PC:			sprintf(info->s, "PC:%04X", h6280.pc.d); break;
600         case CPUINFO_STR_REGISTER + H6280_S:			sprintf(info->s, "S:%02X", h6280.sp.b.l); break;
601         case CPUINFO_STR_REGISTER + H6280_P:			sprintf(info->s, "P:%02X", h6280.p); break;
602         case CPUINFO_STR_REGISTER + H6280_A:			sprintf(info->s, "A:%02X", h6280.a); break;
603 		case CPUINFO_STR_REGISTER + H6280_X:			sprintf(info->s, "X:%02X", h6280.x); break;
604 		case CPUINFO_STR_REGISTER + H6280_Y:			sprintf(info->s, "Y:%02X", h6280.y); break;
605 		case CPUINFO_STR_REGISTER + H6280_IRQ_MASK:		sprintf(info->s, "IM:%02X", h6280.irq_mask); break;
606 		case CPUINFO_STR_REGISTER + H6280_TIMER_STATE:	sprintf(info->s, "TMR:%02X", h6280.timer_status); break;
607 		case CPUINFO_STR_REGISTER + H6280_NMI_STATE:	sprintf(info->s, "NMI:%X", h6280.nmi_state); break;
608 		case CPUINFO_STR_REGISTER + H6280_IRQ1_STATE:	sprintf(info->s, "IRQ1:%X", h6280.irq_state[0]); break;
609 		case CPUINFO_STR_REGISTER + H6280_IRQ2_STATE:	sprintf(info->s, "IRQ2:%X", h6280.irq_state[1]); break;
610 		case CPUINFO_STR_REGISTER + H6280_IRQT_STATE:	sprintf(info->s, "IRQT:%X", h6280.irq_state[2]); break;
611 		case CPUINFO_STR_REGISTER + H6280_M1:			sprintf(info->s, "M1:%02X", h6280.mmr[0]); break;
612 		case CPUINFO_STR_REGISTER + H6280_M2:			sprintf(info->s, "M2:%02X", h6280.mmr[1]); break;
613 		case CPUINFO_STR_REGISTER + H6280_M3:			sprintf(info->s, "M3:%02X", h6280.mmr[2]); break;
614 		case CPUINFO_STR_REGISTER + H6280_M4:			sprintf(info->s, "M4:%02X", h6280.mmr[3]); break;
615 		case CPUINFO_STR_REGISTER + H6280_M5:			sprintf(info->s, "M5:%02X", h6280.mmr[4]); break;
616 		case CPUINFO_STR_REGISTER + H6280_M6:			sprintf(info->s, "M6:%02X", h6280.mmr[5]); break;
617 		case CPUINFO_STR_REGISTER + H6280_M7:			sprintf(info->s, "M7:%02X", h6280.mmr[6]); break;
618 		case CPUINFO_STR_REGISTER + H6280_M8:			sprintf(info->s, "M8:%02X", h6280.mmr[7]); break;
619 	}
620 }
621 #endif
622