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