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