1 /*****************************************************************************
2  *
3  *   upd7810.c
4  *   Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 emulator V0.3
5  *
6  *   Copyright (c) 2001 Juergen Buchmueller, all rights reserved.
7  *
8  *   Copyright (C) 1998,1999,2000 Juergen Buchmueller, all rights reserved.
9  *   You can contact me at juergen@mame.net or pullmoll@stop1984.com
10  *
11  *   - This source code is released as freeware for non-commercial purposes
12  *     as part of the M.A.M.E. (Multiple Arcade Machine Emulator) project.
13  *     The licensing terms of MAME apply to this piece of code for the MAME
14  *     project and derviative works, as defined by the MAME license. You
15  *     may opt to make modifications, improvements or derivative works under
16  *     that same conditions, and the MAME project may opt to keep
17  *     modifications, improvements or derivatives under their terms exclusively.
18  *
19  *   - Alternatively you can choose to apply the terms of the "GPL" (see
20  *     below) to this - and only this - piece of code or your derivative works.
21  *     Note that in no case your choice can have any impact on any other
22  *     source code of the MAME project, or binary, or executable, be it closely
23  *     or losely related to this piece of code.
24  *
25  *  -  At your choice you are also free to remove either licensing terms from
26  *     this file and continue to use it under only one of the two licenses. Do this
27  *     if you think that licenses are not compatible (enough) for you, or if you
28  *     consider either license 'too restrictive' or 'too free'.
29  *
30  *  -  GPL (GNU General Public License)
31  *     This program is free software; you can redistribute it and/or
32  *     modify it under the terms of the GNU General Public License
33  *     as published by the Free Software Foundation; either version 2
34  *     of the License, or (at your option) any later version.
35  *
36  *     This program is distributed in the hope that it will be useful,
37  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
38  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39  *     GNU General Public License for more details.
40  *
41  *     You should have received a copy of the GNU General Public License
42  *     along with this program; if not, write to the Free Software
43  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
44  *
45  *
46  *  This work is based on the
47  *  "NEC Electronics User's Manual, April 1987"
48  *
49  * NS20030115:
50  * - fixed INRW_wa()
51  * - TODO: add 7807, differences are listed below.
52  *       I only added support for these opcodes needed by homedata.c (yes, I am
53  *       lazy):
54  *       4C CE (MOV A,PT)
55  *       48 AC (EXA)
56  *       48 AD (EXR)
57  *       48 AE (EXH)
58  *       48 AF (EXX)
59  *       50 xx (SKN bit)
60  *       58 xx (SETB)
61  *       5B xx (CLR)
62  *       5D xx (SK bit)
63  *
64  *****************************************************************************/
65 /* Hau around 23 May 2004
66   gta, gti, dgt fixed
67   working reg opcodes fixed
68   sio input fixed
69 --
70   PeT around 19 February 2002
71   type selection/gamemaster support added
72   gamemaster init hack? added
73   ORAX added
74   jre negativ fixed
75   prefixed opcodes skipping fixed
76   interrupts fixed and improved
77   sub(and related)/add/daa flags fixed
78   mvi ports,... fixed
79   rll, rlr, drll, drlr fixed
80   rets fixed
81   l0, l1 skipping fixed
82   calt fixed
83 */
84 
85 /*
86 
87 7807 DESCRIPTION
88 
89 
90 
91    PA0  1     64 Vcc
92    PA1  2     63 Vdd
93    PA2  3     62 PD7/AD7
94    PA3  4     61 PD6/AD6
95    PA4  5     60 PD5/AD5
96    PA5  6     59 PD4/AD4
97    PA6  7     58 PD3/AD3
98    PA7  8     57 PD2/AD2
99    PB0  9     56 PD1/AD1
100    PB1 10     55 PD0/AD0
101    PB2 11     54 PF7/AB15
102    PB3 12     53 PF6/AB14
103    PB4 13     52 PF5/AB13
104    PB5 14     51 PF4/AB12
105    PB6 15     50 PF3/AB11
106    PB7 16     49 PF2/AB10
107    PC0 17     48 PF1/AB9
108    PC1 18     47 PF0/AB8
109    PC2 19     46 ALE
110    PC3 20     45 WR*
111    PC4 21     44 RD*
112    PC5 22     43 HLDA
113    PC6 23     42 HOLD
114    PC7 24     41 PT7
115   NMI* 25     40 PT6
116   INT1 26     39 PT5
117  MODE1 27     38 PT4
118 RESET* 28     37 PT3
119  MODE0 29     36 PT2
120     X2 30     35 PT1
121     X1 31     34 PT0
122    Vss 32     33 Vth
123 
124 PA, PB, PC, PD, and PF is bidirectional I/O port
125 and PT is comparator input port in uPD7808.
126 uPD7807 uses PD port as data I/O and bottom address output,
127 and uses PF port as top address output.
128 
129 NMI* is non maskable interrupt input signal (negative edge trigger).
130 
131 INT1 is interrupt input (positive edge trigger). It can be used as
132 AC zero-cross input or trigger source of 16bit timer counter.
133 
134 MODE0 and MODE1 is input terminal which decides total amount of
135 external memory of uPD7807 (4KByte, 16KBYte, and 64KByte).
136 It also decides number of PF ports used as top address output.
137  4KByte mode: PF0~PF3=address output, PF4~PF7=data I/O port
138 16KByte mode: PF0~PF5=address output, PF6~PF7=data I/O port
139 64KByte mode: PF0~PF7=address output
140 
141 RESET* is system rest terminal.
142 
143 X1 and X2 does clock signal generation (connect OSC and condenser).
144 
145 Vth is used to determine threshold voltage for PT port.
146 PT0~PT7 is connected to + input of each comparator,
147 and Vth deterimnes voltage connected to - input of PT0~PT7.
148 But the voltage of Vth is not directly connected to comapators.
149 It is connected via 16-level programmable voltage separate circuit.
150 
151 HOLD and HLDA is terminal for DMA. RD*, WR*, and ALE is bus
152 interface signal (they are same type of Intel 8085).
153 Unlike 8085, I/O address space is not available, so IO /M* signal
154 does not exist. Read/write of external memory can be done
155 by RD*, WR*, and ALE only.
156 
157 Vcc and Vss is main power source. Vdd is backup power source
158 for internal RWM (32 Byte).
159 
160 
161 PA and PB is I/O port. They have control register MA and MB.
162 If control register is set to 1, the port is input.
163 If control register is set to 0, the port is output.
164 They are set to 1 by reset.
165 
166 PT is input-only port. It is consisted of input terminal PT0~PT7
167 and Vth (set threshold voltage). Each PT input has analog comparator
168 and latch, and + input of analog comparator is connected to
169 PT terminal. Every - input of analog comparator is connected
170 to devided voltage of Vth. Voltage dividing level can be set by
171 bottom 4bits of MT (mode T) register. The range is 1/16~16/16 of Vth.
172 
173 Other internal I/Os are
174 8bit timer (x2): Upcounter. If the counter matches to specified value,
175 the timer is reset and counts again from 0.
176 You can also set it to generate interrupt, or invert output flip-flop
177 when the counter matches to specified value.
178 Furthermore, you can output that flip-flop output to PC4/TO output,
179 connect it to clock input of timer/event counter or watchdog timer.
180 Or you can use it as bitrate clock of serial interface.
181 Note: There is only 1 output flip-flop for 2 timers.
182 If you use it for timer output of 1 timer, another timer cannot be used
183 for other than interrupt generator.
184 Clock input for timer can be switched between internal clock (2 type)
185 or PC3/TI input. You can set 1 timer's match-output as another timer's
186 clock input, so that you can use them as 1 16bit timer.
187 
188 16bit timer/event counter (x1): It can be used as
189 - Interval timer
190 - External event counter
191 - Frequency measurement
192 - Pulse width measurement
193 - Programmable rectangle wave output
194 - One pulse output
195 Related terminals are PC5/CI input, PC6/CO0 output, and PC7/CO1.
196 You can measure CI input's H duration, or you can output timing signal
197 (with phase difference) to CO0 and CO1.
198 
199 serial I/F (x1): has 3 modes.
200 - Asynchronous mode
201 - Synchronous mode
202 - I/O interface mode
203 In all 3 modes, bitrate can be internal fixed clock, or timer output,
204 or external clock.
205 In asynchronous mode, you can
206 - switch 7bit/8bit data
207 - set parity ON/OFF and EVEN/ODD
208 - set 1/2 stop bit
209 
210 
211 
212 
213 DIFFERENCES BETWEEN 7810 and 7807
214 
215 --------------------------
216 8bit transfer instructions
217 --------------------------
218 
219 7810
220 inst.     1st byte 2nd byte state   action
221 EXX       00001001            4     Swap BC DE HL
222 EXA       00001000            4     Swap VA EA
223 EXH       01010000            4     Swap HL
224 BLOCK     00110001          13(C+1)  (DE)+ <- (HL)+, C <- C - 1, until CY
225 
226 7807
227 inst.     1st byte  2nd byte state   action
228 EXR       01001000  10101101   8     Swap VA BC DE HL EA
229 EXX       01001000  10101111   8     Swap BC DE HL
230 EXA       01001000  10101100   8     Swap VA EA
231 EXH       01001000  10101110   8     Swap HL
232 BLOCK  D+ 00010000           13(C+1) (DE)+ <- (HL)+, C <- C - 1, until CY
233 BLOCK  D- 00010001           13(C+1) (DE)- <- (HL)-, C <- C - 1, until CY
234 
235 
236 ---------------------------
237 16bit transfer instructions
238 ---------------------------
239 All instructions are same except operand sr4 of DMOV instruction.
240 7810
241 V0-sr4 -function
242  0-ECNT-timer/event counter upcounter
243  1-ECPT-timer/event counter capture
244 
245 7807
246 V1-V0- sr4 -function
247  0- 0-ECNT -timer/event counter upcounter
248  0- 1-ECPT0-timer/event counter capture 0
249  1- 0-ECPT1-timer/event counter capture 1
250 
251 
252 -----------------------------------------
253 8bit operation instructions for registers
254 -----------------------------------------
255 All instructions are same.
256 
257 
258 --------------------------------------
259 8bit operation instructions for memory
260 --------------------------------------
261 All instructions are same.
262 
263 
264 -----------------------------------------
265 Operation instructions for immediate data
266 -----------------------------------------
267 uPD7807 has read-only PT port and special register group sr5 for it.
268 ins.               1st byte  2nd byte 3rd 4th state func
269 GTI    sr5, byte   01100100  s0101sss  dd      14   !CY  sr5 - byte - 1
270 LTI    sr5, byte   01100100  s0111sss  dd      14    CY  sr5 - byte
271 NEI    sr5, byte   01100100  s1101sss  dd      14   !Z   sr5 - byte
272 EQI    sr5, byte   01100100  s1111sss  dd      14    Z   sr5 - byte
273 ONI    sr5, byte   01100100  s1001sss  dd      14   !Z   sr5 & byte
274 OFFI   sr5, byte   01100100  s1011sss  dd      14    Z   sr5 & byte
275 
276 S5-S4-S3-S2-S1-S0-sr -sr1-sr2-sr5-register function
277  0  0  1  1  1  0 --- PT  --- PT  comparator input port T data
278  1  0  0  1  0  0 WDM WDM --- --- watchdog timer mode register
279  1  0  0  1  0  1 MT  --- --- --- port T mode
280 
281 7807 doesn't have registers below
282  0  0  1  0  0  0 ANM ANM ANM     A/D channel mode
283  1  0  0  0  0  0 --- CR0 ---     A/D conversion result 0
284  1  0  0  0  0  1 --- CR1 ---     A/D conversion result 1
285  1  0  0  0  1  0 --- CR2 ---     A/D conversion result 2
286  1  0  0  0  1  1 --- CR3 ---     A/D conversion result 3
287  1  0  1  0  0  0 ZCM --- ---     zero cross mode
288 
289 Special register operand (includes registers for I/O ports) has
290 6 groups - sr, sr1, sr2, sr3, sr4, and sr5. Among these groups,
291 sr, sr1, sr2, and sr5 includes registers described in the table
292 below, and expressed as bit pattern S5-S0.
293 
294 S5S4S3S2S1S0 sr  sr1 sr2 sr5 register function
295 0 0 0 0 0 0  PA  PA  PA  PA  port A
296 0 0 0 0 0 1  PB  PB  PB  PB  port B
297 0 0 0 0 1 0  PC  PC  PC  PC  port C
298 0 0 0 0 1 1  PD  PD  PD  PD  port D
299 0 0 0 1 0 1  PF  PF  PF  PF  port F
300 0 0 0 1 1 0  MKH MKH MKH MKH mask high
301 0 0 0 1 1 1  MKL MKL MKL MKL mask low
302 0 0 1 0 0 1  SMH SMH SMH SMH serial mode high
303 0 0 1 0 1 0  SML --- --- --- serial mode low
304 0 0 1 0 1 1  EOM EOM EOM EOM timer/event counter output mode
305 0 0 1 1 0 0 ETMM --- --- --- timer/event counter mode
306 0 0 1 1 0 1  TMM TMM TMM TMM timer mode
307 0 0 1 1 1 0  --- PT  --- PT  port T
308 0 1 0 0 0 0  MM  --- --- --- memory mapping
309 0 1 0 0 0 1  MCC --- --- --- mode control C
310 0 1 0 0 1 0  MA  --- --- --- mode A
311 0 1 0 0 1 1  MB  --- --- --- mode B
312 0 1 0 1 0 0  MC  --- --- --- mode C
313 0 1 0 1 1 1  MF  --- --- --- mode F
314 0 1 1 0 0 0  TXB --- --- --- Tx buffer
315 0 1 1 0 0 1  --- RXB --- --- Rx buffer
316 0 1 1 0 1 0  TM0 --- --- --- timer register 0
317 0 1 1 0 1 1  TM1 --- --- --- timer register 1
318 1 0 0 1 0 0  WDM WDM --- --- watchdog timer mode
319 1 0 0 1 0 1  MT  --- --- --- mode T
320 
321 For sr and sr1, all 6bits (S5, S4, S3, S2, S1, and S0) are used.
322 For sr2 and sr5, only 4bits (S3, S2, S1, AND S0) are used.
323 They are expressed as 'ssssss' and 's sss' in operation code.
324 Note that 's sss' (of sr2 and sr5) is located separately.
325 S0 is rightmost bit (LSB).
326 
327 
328 --------------------------------------------
329 Operation instructions for working registers
330 --------------------------------------------
331 All instructions are same.
332 
333 
334 --------------------------------------------------------------------------
335 16bit operation instructions and divider/multiplier operation instructions
336 --------------------------------------------------------------------------
337 All instructions are same.
338 
339 
340 ------------------------------------------
341 Increment/decrement operation instructions
342 ------------------------------------------
343 All instructions are same.
344 
345 
346 ----------------------------
347 Other operation instructions
348 ----------------------------
349 7807 has CMC instruction (inverts CY flag).
350 ins. 1st byte 2nd byte 3rd 4th state func
351 CMC  01001000 10101010           8   CY <- !CY
352 
353 
354 ---------------------------
355 Rotation/shift instructions
356 ---------------------------
357 All instructions are same.
358 
359 
360 -----------------------------
361 Jump/call/return instructions
362 -----------------------------
363 All instructions are same.
364 
365 
366 -----------------
367 Skip instructions
368 -----------------
369 7807 doesn't have this
370 ins.            1st byte 2nd byte 3rd 4th state func
371 BIT bit, wa     01011bbb  wwwwwwww          10*  bit skip if (V.wa).bit = 1
372 
373 Instead, 7807 has these bit manipulation instructions.
374 ins.            1st byte 2nd byte 3rd 4th state func
375 MOV    CY, bit  01011111  bbbbbbbb          10* CY <- (bit)
376 MOV    bit, CY  01011010  bbbbbbbb          13* (bit) <- CY
377 AND    CY, bit  00110001  bbbbbbbb          10* CY <- CY & (bit)
378 OR     CY, bit  01011100  bbbbbbbb          10* CY <- CY | (bit)
379 XOR    CY, bit  01011110  bbbbbbbb          10* CY <- CY ^ (bit)
380 SETB   bit      01011000  bbbbbbbb          13* (bit) <- 1
381 CLR    bit      01011011  bbbbbbbb          13* (bit) <- 0
382 NOT    bit      01011001  bbbbbbbb          13* (bit) <- !(bit)
383 SK     bit      01011101  bbbbbbbb          10*  (b) skip if (bit) = 1
384 SKN    bit      01010000  bbbbbbbb          10* !(b) skip if (bit) = 0
385 
386 
387 ------------------------
388 CPU control instructions
389 ------------------------
390 ins.            1st byte 2nd byte 3rd 4th state func
391 HLT             01001000  00111011        11/12 halt
392 11 state in uPD7807 and uPD7810, 12 state in uPD78C10.
393 
394 STOP            01001000  10111011          12  stop
395 7807 doesn't have STOP instruction.
396 
397 */
398 
399 
400 #include "burnint.h"
401 #include "driver.h"
402 #include "state.h"
403 //#include "mamedbg.h"
404 #include "upd7810_intf.h"
405 
core_set_irq(INT32,INT32 line,INT32 state)406 static void core_set_irq(INT32 /*cpu*/, INT32 line, INT32 state)
407 {
408 	upd7810SetIRQLine(line, state);
409 }
410 
411 cpu_core_config upd7810Config =
412 {
413 	"upd7810",
414 	upd7810Open,
415 	upd7810Close,
416 	upd7810CheatRead,
417 	upd7810CheatWrite,
418 	upd7810GetActive,
419 	upd7810TotalCycles,
420 	upd7810NewFrame,
421 	upd7810Idle,
422 	core_set_irq,
423 	upd7810Run,
424 	upd7810RunEnd,
425 	upd7810Reset,
426 	0x10000,
427 	0
428 };
429 
430 static UINT8 (*an0_func)();
431 static UINT8 (*an1_func)();
432 static UINT8 (*an2_func)();
433 static UINT8 (*an3_func)();
434 static UINT8 (*an4_func)();
435 static UINT8 (*an5_func)();
436 static UINT8 (*an6_func)();
437 static UINT8 (*an7_func)();
438 
439 static UINT8 *mem[3][0x100];
440 
441 static UINT8 (*read_byte_8)(UINT16) = NULL;
442 static void (*write_byte_8)(UINT16,UINT8) = NULL;
443 
444 static UINT8 (*io_read_byte_8)(UINT8) = NULL;
445 static void (*io_write_byte_8)(UINT8,UINT8) = NULL;
446 
dummy_write(UINT16,UINT8)447 static void dummy_write(UINT16,UINT8) {}
dummy_read(UINT16)448 static UINT8 dummy_read(UINT16) { return 0; }
dummy_write_port(UINT8,UINT8)449 static void dummy_write_port(UINT8,UINT8) {}
dummy_read_port(UINT8)450 static UINT8 dummy_read_port(UINT8) { return 0; }
451 
cpu_readop(UINT16 address)452 static UINT8 cpu_readop(UINT16 address)
453 {
454 	if (mem[2][address/0x100]) {
455 		return mem[2][address/0x100][address & 0xff];
456 	}
457 
458 	if (read_byte_8) {
459 		return read_byte_8(address);
460 	}
461 
462 	return 0;
463 }
464 
cpu_readop_arg(UINT16 address)465 static UINT8 cpu_readop_arg(UINT16 address)
466 {
467 	if (mem[0][address/0x100]) {
468 		return mem[0][address/0x100][address & 0xff];
469 	}
470 
471 	if (read_byte_8) {
472 		return read_byte_8(address);
473 	}
474 
475 	return 0;
476 }
477 
program_read_byte_8(UINT16 address)478 static UINT8 program_read_byte_8(UINT16 address)
479 {
480 	if (mem[2][address/0x100]) {
481 		return mem[0][address/0x100][address & 0xff];
482 	}
483 
484 	if (read_byte_8) {
485 		return read_byte_8(address);
486 	}
487 
488 	return 0;
489 }
490 
program_write_byte_8(UINT16 address,UINT8 data)491 static void program_write_byte_8(UINT16 address, UINT8 data)
492 {
493 	if (mem[1][address/0x100]) {
494 		mem[1][address/0x100][address & 0xff] = data;
495 		return;
496 	}
497 
498 	if (write_byte_8) {
499 		write_byte_8(address,data);
500 		return;
501 	}
502 }
503 
upd7810CheatWrite(UINT32 address,UINT8 data)504 void upd7810CheatWrite(UINT32 address, UINT8 data)
505 {
506 	if (mem[0][address/0x100]) {
507 		mem[0][address/0x100][address & 0xff] = data;
508 	}
509 	if (mem[1][address/0x100]) {
510 		mem[1][address/0x100][address & 0xff] = data;
511 	}
512 	if (mem[2][address/0x100]) {
513 		mem[2][address/0x100][address & 0xff] = data;
514 	}
515 }
516 
upd7810CheatRead(UINT32 address)517 UINT8 upd7810CheatRead(UINT32 address)
518 {
519 	return program_read_byte_8(address);
520 }
521 
upd7810SetReadPortHandler(UINT8 (* read_port)(UINT8))522 void upd7810SetReadPortHandler(UINT8 (*read_port)(UINT8))
523 {
524 	io_read_byte_8 = read_port;
525 }
526 
upd7810SetWritePortHandler(void (* write_port)(UINT8,UINT8))527 void upd7810SetWritePortHandler(void (*write_port)(UINT8,UINT8))
528 {
529 	io_write_byte_8 = write_port;
530 }
531 
upd7810SetReadHandler(UINT8 (* read)(UINT16))532 void upd7810SetReadHandler(UINT8 (*read)(UINT16))
533 {
534 	read_byte_8 = read;
535 }
536 
upd7810SetWriteHandler(void (* write)(UINT16,UINT8))537 void upd7810SetWriteHandler(void (*write)(UINT16,UINT8))
538 {
539 	write_byte_8 = write;
540 }
541 
upd7810MapMemory(UINT8 * src,UINT16 start,UINT16 finish,UINT8 map)542 void upd7810MapMemory(UINT8 *src, UINT16 start, UINT16 finish, UINT8 map)
543 {
544 	UINT16 len = (finish-start) >> 8;
545 
546 	for (INT32 i = 0; i < len+1; i++)
547 	{
548 		UINT32 offset = i + (start >> 8);
549 		if (map & (1 << 0)) mem[0][offset] = src + (i << 8);
550 		if (map & (1 << 1)) mem[1][offset] = src + (i << 8);
551 		if (map & (1 << 2)) mem[2][offset] = src + (i << 8);
552 	}
553 }
554 
555 
556 static const struct opcode_s *opXX; // = opXX_7810;
557 static INT32 upd7810_config_type = TYPE_7810;
558 INT32 (*upd7810_io_callback)(INT32 ioline, INT32 state) = NULL;
559 INT32 (*upd7810_irq_callback)(INT32 line) = NULL;
560 #define	change_pc(x)	PC = (x)
561 
562 
563 static UPD7810 upd7810;
564 static int upd7810_icount;
565 static int upd7810_total_cycles;
566 static int upd7810_current_cycles;
567 
568 #if 0
569 /* Layout of the registers in the debugger */
570 static UINT8 upd7810_reg_layout[] = {
571 	UPD7810_PC, UPD7810_PSW, UPD7810_A, UPD7810_V, UPD7810_EA, UPD7810_BC, UPD7810_DE, UPD7810_HL, -1,
572 	UPD7810_SP, UPD7810_MM, UPD7810_A2, UPD7810_V2, UPD7810_EA2, UPD7810_BC2, UPD7810_DE2, UPD7810_HL2, -1,
573 	UPD7810_TMM, UPD7810_CNT0, UPD7810_TM0, UPD7810_CNT1, UPD7810_TM1, -1,
574 	UPD7810_ETMM, UPD7810_ECNT, UPD7810_ECPT, UPD7810_ETM0, UPD7810_ETM1, -1,
575 	UPD7810_TXB, UPD7810_RXB, UPD7810_CR0, UPD7810_CR1, UPD7810_CR2, UPD7810_CR3, -1,
576     UPD7810_TXD, UPD7810_RXD, UPD7810_SCK, UPD7810_TI, UPD7810_TO, UPD7810_CI, UPD7810_CO0, UPD7810_CO1, 0
577 };
578 
579 /* Layout of the debugger windows x,y,w,h */
580 static UINT8 upd7810_win_layout[] = {
581 	 0, 0,80, 6,	/* register window (top rows) */
582 	 0, 7,24,15,	/* disassembler window (left colums) */
583 	25, 7,55, 7,	/* memory #1 window (right, upper middle) */
584 	25,15,55, 7,	/* memory #2 window (right, lower middle) */
585 	 0,23,80, 1,	/* command line window (bottom rows) */
586 };
587 #endif
588 
589 #define CY	0x01
590 #define F1	0x02
591 #define L0	0x04
592 #define L1	0x08
593 #define HC	0x10
594 #define SK	0x20
595 #define Z	0x40
596 #define F7	0x80
597 
598 /* IRR flags */
599 #define INTNMI	0x0001
600 #define INTFT0	0x0002
601 #define INTFT1	0x0004
602 #define INTF1	0x0008
603 #define INTF2	0x0010
604 #define INTFE0	0x0020
605 #define INTFE1	0x0040
606 #define INTFEIN 0x0080
607 #define INTFAD	0x0100
608 #define INTFSR	0x0200
609 #define INTFST	0x0400
610 #define INTER	0x0800
611 #define INTOV	0x1000
612 #define INTF0   0x2000
613 
614 /* ITF flags */
615 #define INTAN4	0x0001
616 #define INTAN5	0x0002
617 #define INTAN6	0x0004
618 #define INTAN7	0x0008
619 #define INTSB	0x0010
620 
621 #define PPC 	upd7810.ppc.w.l
622 #define PC		upd7810.pc.w.l
623 #define PCL 	upd7810.pc.b.l
624 #define PCH 	upd7810.pc.b.h
625 #define PCD 	upd7810.pc.d
626 #define SP		upd7810.sp.w.l
627 #define SPL 	upd7810.sp.b.l
628 #define SPH 	upd7810.sp.b.h
629 #define SPD 	upd7810.sp.d
630 #define PSW 	upd7810.psw
631 #define OP		upd7810.op
632 #define OP2 	upd7810.op2
633 #define IFF 	upd7810.iff
634 #define EA		upd7810.ea.w.l
635 #define EAL 	upd7810.ea.b.l
636 #define EAH 	upd7810.ea.b.h
637 #define VA		upd7810.va.w.l
638 #define V		upd7810.va.b.h
639 #define A		upd7810.va.b.l
640 #define VAD 	upd7810.va.d
641 #define BC		upd7810.bc.w.l
642 #define B		upd7810.bc.b.h
643 #define C		upd7810.bc.b.l
644 #define DE		upd7810.de.w.l
645 #define D		upd7810.de.b.h
646 #define E		upd7810.de.b.l
647 #define HL		upd7810.hl.w.l
648 #define H		upd7810.hl.b.h
649 #define L		upd7810.hl.b.l
650 #define EA2 	upd7810.ea2.w.l
651 #define VA2 	upd7810.va2.w.l
652 #define BC2 	upd7810.bc2.w.l
653 #define DE2 	upd7810.de2.w.l
654 #define HL2 	upd7810.hl2.w.l
655 
656 #define OVC0	upd7810.ovc0
657 #define OVC1	upd7810.ovc1
658 #define OVCE	upd7810.ovce
659 #define OVCF	upd7810.ovcf
660 #define OVCS	upd7810.ovcs
661 #define EDGES	upd7810.edges
662 
663 #define CNT0	upd7810.cnt.b.l
664 #define CNT1	upd7810.cnt.b.h
665 #define TM0 	upd7810.tm.b.l
666 #define TM1 	upd7810.tm.b.h
667 #define ECNT	upd7810.ecnt.w.l
668 #define ECPT	upd7810.ecnt.w.h
669 #define ETM0	upd7810.etm.w.l
670 #define ETM1	upd7810.etm.w.h
671 
672 #define MA		upd7810.ma
673 #define MB		upd7810.mb
674 #define MCC 	upd7810.mcc
675 #define MC		upd7810.mc
676 #define MM		upd7810.mm
677 #define MF		upd7810.mf
678 #define TMM 	upd7810.tmm
679 #define ETMM	upd7810.etmm
680 #define EOM 	upd7810.eom
681 #define SML 	upd7810.sml
682 #define SMH 	upd7810.smh
683 #define ANM 	upd7810.anm
684 #define MKL 	upd7810.mkl
685 #define MKH 	upd7810.mkh
686 #define ZCM 	upd7810.zcm
687 
688 #define CR0 	upd7810.cr0
689 #define CR1 	upd7810.cr1
690 #define CR2 	upd7810.cr2
691 #define CR3 	upd7810.cr3
692 #define RXB 	upd7810.rxb
693 #define TXB 	upd7810.txb
694 
695 #define RXD 	upd7810.rxd
696 #define TXD 	upd7810.txd
697 #define SCK 	upd7810.sck
698 #define TI		upd7810.ti
699 #define TO		upd7810.to
700 #define CI		upd7810.ci
701 #define LV0     upd7810.lv0
702 #define LV1     upd7810.lv1
703 #define CO0 	upd7810.co0
704 #define CO1 	upd7810.co1
705 
706 #define IRR 	upd7810.irr
707 #define ITF 	upd7810.itf
708 
709 struct opcode_s {
710 	void (*opfunc)(void);
711 	UINT8 oplen;
712 	UINT8 cycles;
713 	UINT8 cycles_skip;
714 	UINT8 mask_l0_l1;
715 };
716 
717 #define RDOP(O) 	O = cpu_readop(PCD); PC++
718 #define RDOPARG(A)	A = cpu_readop_arg(PCD); PC++
719 #define RM(A)		program_read_byte_8(A)
720 #define WM(A,V) 	program_write_byte_8(A,V)
721 
722 #define ZHC_ADD(after,before,carry) 	\
723 	if (after == 0) PSW |= Z; else PSW &= ~Z; \
724 	if (after == before) \
725 		PSW = (PSW&~CY) | (carry); \
726 	else if (after < before)			\
727 		PSW |= CY;			\
728 	else								\
729 		PSW &= ~CY;				\
730 	if ((after & 15) < (before & 15))	\
731 		PSW |= HC;						\
732 	else								\
733 		PSW &= ~HC; 					\
734 
735 #define ZHC_SUB(after,before,carry) 	\
736 	if (after == 0) PSW |= Z; else PSW &= ~Z; \
737 	if (before == after) 					\
738 		PSW = (PSW & ~CY) | (carry);	\
739 	else if (after > before)			\
740 		PSW |= CY;			\
741 	else								\
742 		PSW &= ~CY;				\
743 	if ((after & 15) > (before & 15))	\
744 		PSW |= HC;						\
745 	else								\
746 		PSW &= ~HC; 					\
747 
748 #define SKIP_CY 	if (CY == (PSW & CY)) PSW |= SK
749 #define SKIP_NC 	if (0 == (PSW & CY)) PSW |= SK
750 #define SKIP_Z		if (Z == (PSW & Z)) PSW |= SK
751 #define SKIP_NZ 	if (0 == (PSW & Z)) PSW |= SK
752 #define SET_Z(n)	if (n) PSW &= ~Z; else PSW |= Z
753 
RP(INT32 port)754 static UINT8 RP(INT32 port)
755 {
756 	UINT8 data = 0xff;
757 	switch (port)
758 	{
759 	case UPD7810_PORTA:
760 		if (upd7810.ma)	// NS20031301 no need to read if the port is set as output
761 			upd7810.pa_in = io_read_byte_8(port);
762 		data = (upd7810.pa_in & upd7810.ma) | (upd7810.pa_out & ~upd7810.ma);
763 		break;
764 	case UPD7810_PORTB:
765 		if (upd7810.mb)	// NS20031301 no need to read if the port is set as output
766 			upd7810.pb_in = io_read_byte_8(port);
767 		data = (upd7810.pb_in & upd7810.mb) | (upd7810.pb_out & ~upd7810.mb);
768 		break;
769 	case UPD7810_PORTC:
770 		if (upd7810.mc)	// NS20031301 no need to read if the port is set as output
771 			upd7810.pc_in = io_read_byte_8(port);
772 		data = (upd7810.pc_in & upd7810.mc) | (upd7810.pc_out & ~upd7810.mc);
773 		if (upd7810.mcc & 0x01) 	/* PC0 = TxD output */
774 			data = (data & ~0x01) | (upd7810.txd & 1 ? 0x01 : 0x00);
775 		if (upd7810.mcc & 0x02) 	/* PC1 = RxD input */
776 			data = (data & ~0x02) | (upd7810.rxd & 1 ? 0x02 : 0x00);
777 		if (upd7810.mcc & 0x04) 	/* PC2 = SCK input/output */
778 			data = (data & ~0x04) | (upd7810.sck & 1 ? 0x04 : 0x00);
779 		if (upd7810.mcc & 0x08) 	/* PC3 = TI input */
780 			data = (data & ~0x08) | (upd7810.ti & 1 ? 0x08 : 0x00);
781 		if (upd7810.mcc & 0x10) 	/* PC4 = TO output */
782 			data = (data & ~0x10) | (upd7810.to & 1 ? 0x10 : 0x00);
783 		if (upd7810.mcc & 0x20) 	/* PC5 = CI input */
784 			data = (data & ~0x20) | (upd7810.ci & 1 ? 0x20 : 0x00);
785 		if (upd7810.mcc & 0x40) 	/* PC6 = CO0 output */
786 			data = (data & ~0x40) | (upd7810.co0 & 1 ? 0x40 : 0x00);
787 		if (upd7810.mcc & 0x80) 	/* PC7 = CO1 output */
788 			data = (data & ~0x80) | (upd7810.co1 & 1 ? 0x80 : 0x00);
789 		break;
790 	case UPD7810_PORTD:
791 		upd7810.pd_in = io_read_byte_8(port);
792 		switch (upd7810.mm & 0x07)
793 		{
794 		case 0x00:			/* PD input mode, PF port mode */
795 			data = upd7810.pd_in;
796 			break;
797 		case 0x01:			/* PD output mode, PF port mode */
798 			data = upd7810.pd_out;
799 			break;
800 		default:			/* PD extension mode, PF port/extension mode */
801 			data = 0xff;	/* what do we see on the port here? */
802 			break;
803 		}
804 		break;
805 	case UPD7810_PORTF:
806 		upd7810.pf_in = io_read_byte_8(port);
807 		switch (upd7810.mm & 0x06)
808 		{
809 		case 0x00:			/* PD input/output mode, PF port mode */
810 			data = (upd7810.pf_in & upd7810.mf) | (upd7810.pf_out & ~upd7810.mf);
811 			break;
812 		case 0x02:			/* PD extension mode, PF0-3 extension mode, PF4-7 port mode */
813 			data = (upd7810.pf_in & upd7810.mf) | (upd7810.pf_out & ~upd7810.mf);
814 			data |= 0x0f;	/* what would we see on the lower bits here? */
815 			break;
816 		case 0x04:			/* PD extension mode, PF0-5 extension mode, PF6-7 port mode */
817 			data = (upd7810.pf_in & upd7810.mf) | (upd7810.pf_out & ~upd7810.mf);
818 			data |= 0x3f;	/* what would we see on the lower bits here? */
819 			break;
820 		case 0x06:
821 			data = 0xff;	/* what would we see on the lower bits here? */
822 			break;
823 		}
824 		break;
825 	case UPD7807_PORTT:	// NS20031301 partial implementation
826 		data = io_read_byte_8(port);
827 		break;
828 	//default:
829 	//	logerror("uPD7810 internal error: RP() called with invalid port number\n");
830 	}
831 	return data;
832 }
833 
WP(INT32 port,UINT8 data)834 static void WP(INT32 port, UINT8 data)
835 {
836 	switch (port)
837 	{
838 	case UPD7810_PORTA:
839 		upd7810.pa_out = data;
840 //      data = (data & ~upd7810.ma) | (upd7810.pa_in & upd7810.ma);
841 		data = (data & ~upd7810.ma) | (upd7810.ma);	// NS20031401
842 		io_write_byte_8(port, data);
843 		break;
844 	case UPD7810_PORTB:
845 		upd7810.pb_out = data;
846 //      data = (data & ~upd7810.mb) | (upd7810.pb_in & upd7810.mb);
847 		data = (data & ~upd7810.mb) | (upd7810.mb);	// NS20031401
848 		io_write_byte_8(port, data);
849 		break;
850 	case UPD7810_PORTC:
851 		upd7810.pc_out = data;
852 //      data = (data & ~upd7810.mc) | (upd7810.pc_in & upd7810.mc);
853 		data = (data & ~upd7810.mc) | (upd7810.mc);	// NS20031401
854 		if (upd7810.mcc & 0x01) 	/* PC0 = TxD output */
855 			data = (data & ~0x01) | (upd7810.txd & 1 ? 0x01 : 0x00);
856 		if (upd7810.mcc & 0x02) 	/* PC1 = RxD input */
857 			data = (data & ~0x02) | (upd7810.rxd & 1 ? 0x02 : 0x00);
858 		if (upd7810.mcc & 0x04) 	/* PC2 = SCK input/output */
859 			data = (data & ~0x04) | (upd7810.sck & 1 ? 0x04 : 0x00);
860 		if (upd7810.mcc & 0x08) 	/* PC3 = TI input */
861 			data = (data & ~0x08) | (upd7810.ti & 1 ? 0x08 : 0x00);
862 		if (upd7810.mcc & 0x10) 	/* PC4 = TO output */
863 			data = (data & ~0x10) | (upd7810.to & 1 ? 0x10 : 0x00);
864 		if (upd7810.mcc & 0x20) 	/* PC5 = CI input */
865 			data = (data & ~0x20) | (upd7810.ci & 1 ? 0x20 : 0x00);
866 		if (upd7810.mcc & 0x40) 	/* PC6 = CO0 output */
867 			data = (data & ~0x40) | (upd7810.co0 & 1 ? 0x40 : 0x00);
868 		if (upd7810.mcc & 0x80) 	/* PC7 = CO1 output */
869 			data = (data & ~0x80) | (upd7810.co1 & 1 ? 0x80 : 0x00);
870 		io_write_byte_8(port, data);
871 		break;
872 	case UPD7810_PORTD:
873 		upd7810.pd_out = data;
874 		switch (upd7810.mm & 0x07)
875 		{
876 		case 0x00:			/* PD input mode, PF port mode */
877 			data = upd7810.pd_in;
878 			break;
879 		case 0x01:			/* PD output mode, PF port mode */
880 			data = upd7810.pd_out;
881 			break;
882 		default:			/* PD extension mode, PF port/extension mode */
883 			return;
884 		}
885 		io_write_byte_8(port, data);
886 		break;
887 	case UPD7810_PORTF:
888 		upd7810.pf_out = data;
889 		data = (data & ~upd7810.mf) | (upd7810.pf_in & upd7810.mf);
890 		switch (upd7810.mm & 0x06)
891 		{
892 		case 0x00:			/* PD input/output mode, PF port mode */
893 			break;
894 		case 0x02:			/* PD extension mode, PF0-3 extension mode, PF4-7 port mode */
895 			data |= 0x0f;	/* what would come out for the lower bits here? */
896 			break;
897 		case 0x04:			/* PD extension mode, PF0-5 extension mode, PF6-7 port mode */
898 			data |= 0x3f;	/* what would come out for the lower bits here? */
899 			break;
900 		case 0x06:
901 			data |= 0xff;	/* what would come out for the lower bits here? */
902 			break;
903 		}
904 		io_write_byte_8(port, data);
905 		break;
906 	//default:
907 	//	logerror("uPD7810 internal error: RP() called with invalid port number\n");
908 	}
909 }
910 
upd7810_take_irq(void)911 static void upd7810_take_irq(void)
912 {
913 	UINT16 vector = 0;
914 	int irqline = 0;
915 
916 	/* global interrupt disable? */
917 	if (0 == IFF)
918 		return;
919 
920 	/* check the interrupts in priority sequence */
921 	if (IRR & INTNMI)
922 	{
923 		/* Nonmaskable interrupt */
924 		irqline = CPU_IRQLINE_NMI;
925 		vector = 0x0004;
926 		IRR &= ~INTNMI;
927 	}
928 	else
929 	if ((IRR & INTFT0)  && 0 == (MKL & 0x02))
930 	{
931 		vector = 0x0008;
932 		if (!((IRR & INTFT1)    && 0 == (MKL & 0x04)))
933 		IRR&=~INTFT0;
934 	}
935 	else
936 	if ((IRR & INTFT1)  && 0 == (MKL & 0x04))
937 	{
938 		vector = 0x0008;
939 		IRR&=~INTFT1;
940 	}
941 	else
942 	if ((IRR & INTF1)	&& 0 == (MKL & 0x08))
943 	{
944 		irqline = UPD7810_INTF1;
945 		vector = 0x0010;
946 		if (!((IRR & INTF2)	&& 0 == (MKL & 0x10)))
947 		    IRR&=~INTF1;
948 	}
949 	else
950 	if ((IRR & INTF2)	&& 0 == (MKL & 0x10))
951 	{
952 		irqline = UPD7810_INTF2;
953 		vector = 0x0010;
954 		IRR&=~INTF2;
955 	}
956 	else
957 	if ((IRR & INTFE0)  && 0 == (MKL & 0x20))
958 	{
959 		vector = 0x0018;
960 		if (!((IRR & INTFE1)    && 0 == (MKL & 0x40)))
961 		IRR&=~INTFE0;
962 	}
963 	else
964 	if ((IRR & INTFE1)  && 0 == (MKL & 0x40))
965 	{
966 		vector = 0x0018;
967 		IRR&=~INTFE1;
968 	}
969 	else
970 	if ((IRR & INTFEIN) && 0 == (MKL & 0x80))
971 	{
972 		vector = 0x0020;
973 	}
974 	else
975 	if ((IRR & INTFAD)	&& 0 == (MKH & 0x01))
976 	{
977 		vector = 0x0020;
978 	}
979 	else
980 	if ((IRR & INTFSR)	&& 0 == (MKH & 0x02))
981 	{
982 		vector = 0x0028;
983 		IRR&=~INTFSR;
984 	}
985 	else
986 	if ((IRR & INTFST)	&& 0 == (MKH & 0x04))
987 	{
988 		vector = 0x0028;
989 	   	IRR&=~INTFST;
990 	}
991 
992 	if (vector)
993 	{
994 		/* acknowledge external IRQ */
995 		if (irqline && upd7810_irq_callback)
996 			(*upd7810_irq_callback)(irqline);
997 		SP--;
998 		WM( SP, PSW );
999 		SP--;
1000 		WM( SP, PCH );
1001 		SP--;
1002 		WM( SP, PCL );
1003 		IFF = 0;
1004 		PSW &= ~(SK|L0|L1);
1005 		PC = vector;
1006 	}
1007 }
1008 
upd7810_co0_output_change()1009 static void upd7810_co0_output_change()
1010 {
1011 	/* Output LV0 Content to CO0 */
1012 	CO0 = LV0;
1013 
1014 	/* LV0 Level Inversion */
1015 	if (EOM & 0x02)
1016 		LV0 ^= 1;
1017 
1018 	//m_co0_func(CO0);
1019 }
1020 
upd7810_co1_output_change()1021 static void upd7810_co1_output_change()
1022 {
1023 	/* Output LV1 Content to CO1 */
1024 	CO1 = LV1;
1025 
1026 	/* LV1 Level Inversion */
1027 	if (EOM & 0x20)
1028 		LV1 ^= 1;
1029 
1030 	//m_co1_func(CO1);
1031 }
1032 
upd7810_write_EOM()1033 static void upd7810_write_EOM()
1034 {
1035 	switch (EOM & 0x0c)
1036 	{
1037 	case 0x04:  /* To Reset LV0 */
1038 		LV0 = 0;
1039 		EOM &= 0xfb; /* LRE0 is reset to 0 */
1040 		break;
1041 	case 0x08:  /* To Set LV0 */
1042 		LV0 = 1;
1043 		EOM &= 0xf7; /* LRE1 is reset to 0 */
1044 		break;
1045 	}
1046 	/* Output LV0 Content */
1047 	if (EOM & 0x01) {
1048 		upd7810_co0_output_change();
1049 		EOM &= 0xfe; /* LO0 is reset to 0 */
1050 	}
1051 
1052 	switch (EOM & 0xc0)
1053 	{
1054 	case 0x40:  /* To Reset LV1 */
1055 		LV1 = 0;
1056 		EOM &= 0xbf; /* LRE2 is reset to 0 */
1057 		break;
1058 	case 0x80:  /* To Set LV1 */
1059 		LV1 = 1;
1060 		EOM &= 0x7f; /* LRE3 is reset to 0 */
1061 		break;
1062 	}
1063 	/* Output LV1 Content */
1064 	if (EOM & 0x10) {
1065 		upd7810_co1_output_change();
1066 		EOM &= 0xef; /* LO1 is reset to 0 */
1067 	}
1068 }
1069 
1070 #if 0
1071 OLD
1072 static void upd7810_write_EOM(void)
1073 {
1074 	if (EOM & 0x01) /* output LV0 content ? */
1075 	{
1076 		switch (EOM & 0x0e)
1077 		{
1078 		case 0x02:	/* toggle CO0 */
1079 			CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
1080 			break;
1081 		case 0x04:	/* reset CO0 */
1082 			CO0 = 0;
1083 			break;
1084 		case 0x08:	/* set CO0 */
1085 			CO0 = 1;
1086 			break;
1087 		}
1088 	}
1089 	if (EOM & 0x10) /* output LV0 content ? */
1090 	{
1091 		switch (EOM & 0xe0)
1092 		{
1093 		case 0x20:	/* toggle CO1 */
1094 			CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
1095 			break;
1096 		case 0x40:	/* reset CO1 */
1097 			CO1 = 0;
1098 			break;
1099 		case 0x80:	/* set CO1 */
1100 			CO1 = 1;
1101 			break;
1102 		}
1103 	}
1104 }
1105 #endif
1106 
upd7810_write_TXB(void)1107 static void upd7810_write_TXB(void)
1108 {
1109 	upd7810.txbuf = 1;
1110 }
1111 
1112 #define PAR7(n) ((((n)>>6)^((n)>>5)^((n)>>4)^((n)>>3)^((n)>>2)^((n)>>1)^((n)))&1)
1113 #define PAR8(n) ((((n)>>7)^((n)>>6)^((n)>>5)^((n)>>4)^((n)>>3)^((n)>>2)^((n)>>1)^((n)))&1)
1114 
upd7810_sio_output(void)1115 static void upd7810_sio_output(void)
1116 {
1117 	/* shift out more bits? */
1118 	if (upd7810.txcnt > 0)
1119 	{
1120 		TXD = upd7810.txs & 1;
1121 		if (upd7810_io_callback)
1122 			(*upd7810_io_callback)(UPD7810_TXD,TXD);
1123 		upd7810.txs >>= 1;
1124 		upd7810.txcnt--;
1125 		if (0 == upd7810.txcnt)
1126 			IRR |= INTFST;		/* serial transfer completed */
1127 	}
1128 	else
1129 	if (SMH & 0x04) /* send enable ? */
1130 	{
1131 		/* nothing written into the transmitter buffer ? */
1132         if (0 == upd7810.txbuf)
1133 			return;
1134         upd7810.txbuf = 0;
1135 
1136         if (SML & 0x03)         /* asynchronous mode ? */
1137 		{
1138 			switch (SML & 0xfc)
1139 			{
1140 			case 0x48:	/* 7bits, no parity, 1 stop bit */
1141 			case 0x68:	/* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
1142 				/* insert start bit in bit0, stop bit int bit8 */
1143 				upd7810.txs = (TXB << 1) | (1 << 8);
1144 				upd7810.txcnt = 9;
1145 				break;
1146 			case 0x4c:	/* 8bits, no parity, 1 stop bit */
1147 			case 0x6c:	/* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
1148 				/* insert start bit in bit0, stop bit int bit9 */
1149 				upd7810.txs = (TXB << 1) | (1 << 9);
1150 				upd7810.txcnt = 10;
1151 				break;
1152 			case 0x58:	/* 7bits, odd parity, 1 stop bit */
1153 				/* insert start bit in bit0, parity in bit 8, stop bit in bit9 */
1154 				upd7810.txs = (TXB << 1) | (PAR7(TXB) << 8) | (1 << 9);
1155 				upd7810.txcnt = 10;
1156 				break;
1157 			case 0x5c:	/* 8bits, odd parity, 1 stop bit */
1158 				/* insert start bit in bit0, parity in bit 9, stop bit int bit10 */
1159 				upd7810.txs = (TXB << 1) | (PAR8(TXB) << 9) | (1 << 10);
1160 				upd7810.txcnt = 11;
1161 				break;
1162 			case 0x78:	/* 7bits, even parity, 1 stop bit */
1163 				/* insert start bit in bit0, parity in bit 8, stop bit in bit9 */
1164 				upd7810.txs = (TXB << 1) | ((PAR7(TXB) ^ 1) << 8) | (1 << 9);
1165 				upd7810.txcnt = 10;
1166 				break;
1167 			case 0x7c:	/* 8bits, even parity, 1 stop bit */
1168 				/* insert start bit in bit0, parity in bit 9, stop bit int bit10 */
1169 				upd7810.txs = (TXB << 1) | ((PAR8(TXB) ^ 1) << 9) | (1 << 10);
1170 				upd7810.txcnt = 11;
1171 				break;
1172 			case 0xc8:	/* 7bits, no parity, 2 stop bits */
1173 			case 0xe8:	/* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
1174 				/* insert start bit in bit0, stop bits int bit8+9 */
1175 				upd7810.txs = (TXB << 1) | (3 << 8);
1176 				upd7810.txcnt = 10;
1177 				break;
1178 			case 0xcc:	/* 8bits, no parity, 2 stop bits */
1179 			case 0xec:	/* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
1180 				/* insert start bit in bit0, stop bits in bits9+10 */
1181 				upd7810.txs = (TXB << 1) | (3 << 9);
1182 				upd7810.txcnt = 11;
1183 				break;
1184 			case 0xd8:	/* 7bits, odd parity, 2 stop bits */
1185 				/* insert start bit in bit0, parity in bit 8, stop bits in bits9+10 */
1186 				upd7810.txs = (TXB << 1) | (PAR7(TXB) << 8) | (3 << 9);
1187 				upd7810.txcnt = 11;
1188 				break;
1189 			case 0xdc:	/* 8bits, odd parity, 2 stop bits */
1190 				/* insert start bit in bit0, parity in bit 9, stop bits int bit10+11 */
1191 				upd7810.txs = (TXB << 1) | (PAR8(TXB) << 9) | (3 << 10);
1192 				upd7810.txcnt = 12;
1193 				break;
1194 			case 0xf8:	/* 7bits, even parity, 2 stop bits */
1195 				/* insert start bit in bit0, parity in bit 8, stop bits in bit9+10 */
1196 				upd7810.txs = (TXB << 1) | ((PAR7(TXB) ^ 1) << 8) | (3 << 9);
1197 				upd7810.txcnt = 11;
1198 				break;
1199 			case 0xfc:	/* 8bits, even parity, 2 stop bits */
1200 				/* insert start bit in bit0, parity in bit 9, stop bits int bits10+10 */
1201 				upd7810.txs = (TXB << 1) | ((PAR8(TXB) ^ 1) << 9) | (1 << 10);
1202 				upd7810.txcnt = 12;
1203 				break;
1204 			}
1205 		}
1206 		else
1207 		{
1208 			/* synchronous mode */
1209 			upd7810.txs = TXB;
1210 			upd7810.txcnt = 8;
1211 		}
1212 	}
1213 }
1214 
upd7810_sio_input(void)1215 static void upd7810_sio_input(void)
1216 {
1217 	/* sample next bit? */
1218 	if (upd7810.rxcnt > 0)
1219 	{
1220 		if (upd7810_io_callback)
1221 			RXD = (*upd7810_io_callback)(UPD7810_RXD,RXD);
1222 		upd7810.rxs = (upd7810.rxs >> 1) | ((UINT16)RXD << 15);
1223 		upd7810.rxcnt--;
1224 		if (0 == upd7810.rxcnt)
1225 		{
1226 			/* reset the TSK bit */
1227 			SMH &= ~0x40;
1228 			/* serial receive completed interrupt */
1229 			IRR |= INTFSR;
1230 			/* now extract the data from the shift register */
1231 			if (SML & 0x03) 	/* asynchronous mode ? */
1232 			{
1233 				switch (SML & 0xfc)
1234 				{
1235 				case 0x48:	/* 7bits, no parity, 1 stop bit */
1236 				case 0x68:	/* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
1237 					upd7810.rxs >>= 16 - 9;
1238 					RXB = (upd7810.rxs >> 1) & 0x7f;
1239 					if ((1 << 8) != (upd7810.rxs & (1 | (1 << 8))))
1240 						IRR |= INTER;	/* framing error */
1241 					break;
1242 				case 0x4c:	/* 8bits, no parity, 1 stop bit */
1243 				case 0x6c:	/* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
1244 					upd7810.rxs >>= 16 - 10;
1245 					RXB = (upd7810.rxs >> 1) & 0xff;
1246 					if ((1 << 9) != (upd7810.rxs & (1 | (1 << 9))))
1247 						IRR |= INTER;	/* framing error */
1248 					break;
1249 				case 0x58:	/* 7bits, odd parity, 1 stop bit */
1250 					upd7810.rxs >>= 16 - 10;
1251 					RXB = (upd7810.rxs >> 1) & 0x7f;
1252 					if ((1 << 9) != (upd7810.rxs & (1 | (1 << 9))))
1253 						IRR |= INTER;	/* framing error */
1254 					if (PAR7(RXB) != ((upd7810.rxs >> 8) & 1))
1255 						IRR |= INTER;	/* parity error */
1256 					break;
1257 				case 0x5c:	/* 8bits, odd parity, 1 stop bit */
1258 					upd7810.rxs >>= 16 - 11;
1259 					RXB = (upd7810.rxs >> 1) & 0xff;
1260 					if ((1 << 10) != (upd7810.rxs & (1 | (1 << 10))))
1261 						IRR |= INTER;	/* framing error */
1262 					if (PAR8(RXB) != ((upd7810.rxs >> 9) & 1))
1263 						IRR |= INTER;	/* parity error */
1264 					break;
1265 				case 0x78:	/* 7bits, even parity, 1 stop bit */
1266 					upd7810.rxs >>= 16 - 10;
1267 					RXB = (upd7810.rxs >> 1) & 0x7f;
1268 					if ((1 << 9) != (upd7810.rxs & (1 | (1 << 9))))
1269 						IRR |= INTER;	/* framing error */
1270 					if (PAR7(RXB) != ((upd7810.rxs >> 8) & 1))
1271 						IRR |= INTER;	/* parity error */
1272 					break;
1273 				case 0x7c:	/* 8bits, even parity, 1 stop bit */
1274 					upd7810.rxs >>= 16 - 11;
1275 					RXB = (upd7810.rxs >> 1) & 0xff;
1276 					if ((1 << 10) != (upd7810.rxs & (1 | (1 << 10))))
1277 						IRR |= INTER;	/* framing error */
1278 					if (PAR8(RXB) != ((upd7810.rxs >> 9) & 1))
1279 						IRR |= INTER;	/* parity error */
1280 					break;
1281 				case 0xc8:	/* 7bits, no parity, 2 stop bits */
1282 				case 0xe8:	/* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
1283 					upd7810.rxs >>= 16 - 10;
1284 					RXB = (upd7810.rxs >> 1) & 0x7f;
1285 					if ((3 << 9) != (upd7810.rxs & (1 | (3 << 9))))
1286 						IRR |= INTER;	/* framing error */
1287 					if (PAR7(RXB) != ((upd7810.rxs >> 8) & 1))
1288 						IRR |= INTER;	/* parity error */
1289 					break;
1290 				case 0xcc:	/* 8bits, no parity, 2 stop bits */
1291 				case 0xec:	/* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
1292 					upd7810.rxs >>= 16 - 11;
1293 					RXB = (upd7810.rxs >> 1) & 0xff;
1294 					if ((3 << 10) != (upd7810.rxs & (1 | (3 << 10))))
1295 						IRR |= INTER;	/* framing error */
1296 					if (PAR8(RXB) != ((upd7810.rxs >> 9) & 1))
1297 						IRR |= INTER;	/* parity error */
1298 					break;
1299 				case 0xd8:	/* 7bits, odd parity, 2 stop bits */
1300 					upd7810.rxs >>= 16 - 11;
1301 					RXB = (upd7810.rxs >> 1) & 0x7f;
1302 					if ((3 << 10) != (upd7810.rxs & (1 | (3 << 10))))
1303 						IRR |= INTER;	/* framing error */
1304 					if (PAR7(RXB) != ((upd7810.rxs >> 8) & 1))
1305 						IRR |= INTER;	/* parity error */
1306 					break;
1307 				case 0xdc:	/* 8bits, odd parity, 2 stop bits */
1308 					upd7810.rxs >>= 16 - 12;
1309 					RXB = (upd7810.rxs >> 1) & 0xff;
1310 					if ((3 << 11) != (upd7810.rxs & (1 | (3 << 11))))
1311 						IRR |= INTER;	/* framing error */
1312 					if (PAR8(RXB) != ((upd7810.rxs >> 9) & 1))
1313 						IRR |= INTER;	/* parity error */
1314 					break;
1315 				case 0xf8:	/* 7bits, even parity, 2 stop bits */
1316 					upd7810.rxs >>= 16 - 11;
1317 					RXB = (upd7810.rxs >> 1) & 0x7f;
1318 					if ((3 << 10) != (upd7810.rxs & (1 | (3 << 10))))
1319 						IRR |= INTER;	/* framing error */
1320 					if (PAR7(RXB) != ((upd7810.rxs >> 8) & 1))
1321 						IRR |= INTER;	/* parity error */
1322 					break;
1323 				case 0xfc:	/* 8bits, even parity, 2 stop bits */
1324 					upd7810.rxs >>= 16 - 12;
1325 					RXB = (upd7810.rxs >> 1) & 0xff;
1326 					if ((3 << 11) != (upd7810.rxs & (1 | (3 << 11))))
1327 						IRR |= INTER;	/* framing error */
1328 					if (PAR8(RXB) != ((upd7810.rxs >> 9) & 1))
1329 						IRR |= INTER;	/* parity error */
1330 					break;
1331 				}
1332 			}
1333 			else
1334 			{
1335 				upd7810.rxs >>= 16 - 8;
1336 				RXB = upd7810.rxs;
1337 //              upd7810.rxcnt = 8;
1338 			}
1339 		}
1340 	}
1341 	else
1342 	if (SMH & 0x08) /* receive enable ? */
1343 	{
1344 		if (SML & 0x03) 	/* asynchronous mode ? */
1345 		{
1346 			switch (SML & 0xfc)
1347 			{
1348 			case 0x48:	/* 7bits, no parity, 1 stop bit */
1349 			case 0x68:	/* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
1350 				upd7810.rxcnt = 9;
1351 				break;
1352 			case 0x4c:	/* 8bits, no parity, 1 stop bit */
1353 			case 0x6c:	/* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
1354 				upd7810.rxcnt = 10;
1355 				break;
1356 			case 0x58:	/* 7bits, odd parity, 1 stop bit */
1357 				upd7810.rxcnt = 10;
1358 				break;
1359 			case 0x5c:	/* 8bits, odd parity, 1 stop bit */
1360 				upd7810.rxcnt = 11;
1361 				break;
1362 			case 0x78:	/* 7bits, even parity, 1 stop bit */
1363 				upd7810.rxcnt = 10;
1364 				break;
1365 			case 0x7c:	/* 8bits, even parity, 1 stop bit */
1366 				upd7810.rxcnt = 11;
1367 				break;
1368 			case 0xc8:	/* 7bits, no parity, 2 stop bits */
1369 			case 0xe8:	/* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
1370 				upd7810.rxcnt = 10;
1371 				break;
1372 			case 0xcc:	/* 8bits, no parity, 2 stop bits */
1373 			case 0xec:	/* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
1374 				upd7810.rxcnt = 11;
1375 				break;
1376 			case 0xd8:	/* 7bits, odd parity, 2 stop bits */
1377 				upd7810.rxcnt = 11;
1378 				break;
1379 			case 0xdc:	/* 8bits, odd parity, 2 stop bits */
1380 				upd7810.rxcnt = 12;
1381 				break;
1382 			case 0xf8:	/* 7bits, even parity, 2 stop bits */
1383 				upd7810.rxcnt = 11;
1384 				break;
1385 			case 0xfc:	/* 8bits, even parity, 2 stop bits */
1386 				upd7810.rxcnt = 12;
1387 				break;
1388 			}
1389 		}
1390 		else
1391 		/* TSK bit set ? */
1392 		if (SMH & 0x40)
1393 		{
1394 			upd7810.rxcnt = 8;
1395 		}
1396 	}
1397 }
1398 
upd7810_handle_timer0(int cycles,int clkdiv)1399 static void upd7810_handle_timer0(int cycles, int clkdiv)
1400 {
1401 	OVC0 += cycles;
1402 	while (OVC0 >= clkdiv)
1403 	{
1404 		OVC0 -= clkdiv;
1405 		CNT0++;
1406 		if (CNT0 == TM0)
1407 		{
1408 			CNT0 = 0;
1409 			IRR |= INTFT0;
1410 			/* timer F/F source is timer 0 ? */
1411 			if (0x00 == (TMM & 0x03))
1412 			{
1413 				TO ^= 1;
1414 				if (upd7810_io_callback)
1415 					(*upd7810_io_callback)(UPD7810_TO,TO);
1416 			}
1417 			/* timer 1 chained with timer 0 ? */
1418 			if ((TMM & 0xe0) == 0x60)
1419 			{
1420 				CNT1++;
1421 				if (CNT1 == TM1)
1422 				{
1423 					CNT1 = 0;
1424 					IRR |= INTFT1;
1425 					/* timer F/F source is timer 1 ? */
1426 					if (0x01 == (TMM & 0x03))
1427 					{
1428 						TO ^= 1;
1429 						if (upd7810_io_callback)
1430 							(*upd7810_io_callback)(UPD7810_TO,TO);
1431 					}
1432 				}
1433 			}
1434 		}
1435 	}
1436 }
1437 
upd7810_handle_timer1(int cycles,int clkdiv)1438 static void upd7810_handle_timer1(int cycles, int clkdiv)
1439 {
1440 	OVC1 += cycles;
1441 	while (OVC1 >= clkdiv)
1442 	{
1443 		OVC1 -= clkdiv;
1444 		CNT1++;
1445 		if (CNT1 == TM1)
1446 		{
1447 			CNT1 = 0;
1448 			IRR |= INTFT1;
1449 			/* timer F/F source is timer 1 ? */
1450 			if (0x01 == (TMM & 0x03))
1451 			{
1452 				TO ^= 1;
1453 				if (upd7810_io_callback)
1454 					(*upd7810_io_callback)(UPD7810_TO,TO);
1455 			}
1456 		}
1457 	}
1458 }
1459 
upd7810_timers(int cycles)1460 static void upd7810_timers(int cycles)
1461 {
1462 	/**** TIMER 0 ****/
1463 	if (TMM & 0x10)         /* timer 0 upcounter reset ? */
1464 		CNT0 = 0;
1465 	else
1466 	{
1467 		switch (TMM & 0x0c) /* timer 0 clock source */
1468 		{
1469 		case 0x00:  /* clock divided by 12 */
1470 			upd7810_handle_timer0(cycles, 12);
1471 			break;
1472 		case 0x04:  /* clock divided by 384 */
1473 			upd7810_handle_timer0(cycles, 384);
1474 			break;
1475 		case 0x08:  /* external signal at TI */
1476 			break;
1477 		case 0x0c:  /* disabled */
1478 			break;
1479 		}
1480 	}
1481 
1482 	/**** TIMER 1 ****/
1483 	if (TMM & 0x80)         /* timer 1 upcounter reset ? */
1484 		CNT1 = 0;
1485 	else
1486 	{
1487 		switch (TMM & 0x60) /* timer 1 clock source */
1488 		{
1489 		case 0x00:  /* clock divided by 12 */
1490 			upd7810_handle_timer1(cycles, 12);
1491 			break;
1492 		case 0x20:  /* clock divided by 384 */
1493 			upd7810_handle_timer1(cycles, 384);
1494 			break;
1495 		case 0x40:  /* external signal at TI */
1496 			break;
1497 		case 0x60:  /* clocked with timer 0 */
1498 			break;
1499 		}
1500 	}
1501 
1502 	/**** TIMER F/F ****/
1503 	/* timer F/F source is clock divided by 3 ? */
1504 	if (0x02 == (TMM & 0x03))
1505 	{
1506 		OVCF += cycles;
1507 		while (OVCF >= 3)
1508 		{
1509 			TO ^= 1;
1510 			if (upd7810_io_callback)
1511 				(*upd7810_io_callback)(UPD7810_TO,TO);
1512 			OVCF -= 3;
1513 		}
1514 	}
1515 
1516 	/**** ETIMER ****/
1517 	/* ECNT clear */
1518 	if (0x00 == (ETMM & 0x0c))
1519 		ECNT = 0;
1520 	else
1521 	if (0x00 == (ETMM & 0x03) || (0x01 == (ETMM & 0x03) && CI))
1522 	{
1523 		OVCE += cycles;
1524 		/* clock divided by 12 */
1525 		while (OVCE >= 12)
1526 		{
1527 			OVCE -= 12;
1528 			ECNT++;
1529 			/* Interrupt Control Circuit */
1530 			if (ETM0 == ECNT)
1531 				IRR |= INTFE0;
1532 			if (ETM1 == ECNT)
1533 				IRR |= INTFE1;
1534 			/* Conditions When ECNT Causes a CO0 Output Change */
1535 			if (((0x00 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 */
1536 				/* ((0x10 == (ETMM & 0x30)) prohibited */
1537 				((0x20 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 or at falling CI input */
1538 				((0x30 == (ETMM & 0x30)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
1539 			{
1540 				upd7810_co0_output_change();
1541 			}
1542 			/* Conditions When ECNT Causes a CO1 Output Change */
1543 			if (((0x00 == (ETMM & 0xc0)) && (ETM1 == ECNT)) || /* set CO1 if ECNT == ETM1 */
1544 				/* ((0x40 == (ETMM & 0xc0)) prohibited */
1545 				((0x80 == (ETMM & 0xc0)) && (ETM1 == ECNT)) || /* set CO1 if ECNT == ETM1 or at falling CI input */
1546 				((0xc0 == (ETMM & 0xc0)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
1547 			{
1548 				upd7810_co1_output_change();
1549 			}
1550 			/* How and When ECNT is Cleared */
1551 			switch (ETMM & 0x0c)
1552 			{
1553 			case 0x00:              /* clear ECNT */
1554 				break;
1555 			case 0x04:              /* free running */
1556 				if (0 == ECNT)
1557 					ITF |= INTOV;   /* set overflow flag if counter wrapped */
1558 				break;
1559 			case 0x08:              /* reset at falling edge of CI or TO */
1560 				break;
1561 			case 0x0c:              /* reset if ECNT == ETM1 */
1562 				if (ETM1 == ECNT)
1563 					ECNT = 0;
1564 				break;
1565 			}
1566 		}
1567 	}
1568 
1569 	/**** SIO ****/
1570 	switch (SMH & 0x03)
1571 	{
1572 	case 0x00:      /* interval timer F/F */
1573 		break;
1574 	case 0x01:      /* internal clock divided by 384 */
1575 		OVCS += cycles;
1576 		while (OVCS >= 384)
1577 		{
1578 			OVCS -= 384;
1579 			if (0 == (EDGES ^= 1))
1580 				upd7810_sio_input();
1581 			else
1582 				upd7810_sio_output();
1583 		}
1584 		break;
1585 	case 0x02:      /* internal clock divided by 24 */
1586 		OVCS += cycles;
1587 		while (OVCS >= 24)
1588 		{
1589 			OVCS -= 24;
1590 			if (0 == (EDGES ^= 1))
1591 				upd7810_sio_input();
1592 			else
1593 				upd7810_sio_output();
1594 		}
1595 		break;
1596 	}
1597 
1598 	/**** ADC ****/
1599 	upd7810.adcnt += cycles;
1600 	if (upd7810.PANM != ANM)
1601 	{
1602 		/* reset A/D converter */
1603 		upd7810.adcnt = 0;
1604 		if (ANM & 0x10)
1605 			upd7810.adtot = 144;
1606 		else
1607 			upd7810.adtot = 192;
1608 		upd7810.adout = 0;
1609 		upd7810.shdone = 0;
1610 		if (ANM & 0x01)
1611 		{
1612 			/* select mode */
1613 			upd7810.adin = (ANM >> 1) & 0x07;
1614 		}
1615 		else
1616 		{
1617 			/* scan mode */
1618 			upd7810.adin    = 0;
1619 			upd7810.adrange = (ANM >> 1) & 0x04;
1620 		}
1621 	}
1622 	upd7810.PANM = ANM;
1623 	if (ANM & 0x01)
1624 	{
1625 		/* select mode */
1626 		if (upd7810.shdone == 0)
1627 		{
1628 			switch (upd7810.adin)
1629 			{
1630 				case 0: upd7810.tmpcr = an0_func(); break;
1631 				case 1: upd7810.tmpcr = an1_func(); break;
1632 				case 2: upd7810.tmpcr = an2_func(); break;
1633 				case 3: upd7810.tmpcr = an3_func(); break;
1634 				case 4: upd7810.tmpcr = an4_func(); break;
1635 				case 5: upd7810.tmpcr = an5_func(); break;
1636 				case 6: upd7810.tmpcr = an6_func(); break;
1637 				case 7: upd7810.tmpcr = an7_func(); break;
1638 			}
1639 			upd7810.shdone = 1;
1640 		}
1641 		if (upd7810.adcnt > upd7810.adtot)
1642 		{
1643 			upd7810.adcnt -= upd7810.adtot;
1644 			switch (upd7810.adout)
1645 			{
1646 				// volfied code checks bit 0x80, old code set bit 0x01, TODO: verify which bits are set on real hw
1647 				case 0: CR0 = upd7810.tmpcr ? 0xff:0x00; break;
1648 				case 1: CR1 = upd7810.tmpcr ? 0xff:0x00; break;
1649 				case 2: CR2 = upd7810.tmpcr ? 0xff:0x00; break;
1650 				case 3: CR3 = upd7810.tmpcr ? 0xff:0x00; break;
1651 			}
1652 			upd7810.adout = (upd7810.adout + 1) & 0x03;
1653 			if (upd7810.adout == 0)
1654 				IRR |= INTFAD;
1655 			upd7810.shdone = 0;
1656 		}
1657 	}
1658 	else
1659 	{
1660 		/* scan mode */
1661 		if (upd7810.shdone == 0)
1662 		{
1663 			switch (upd7810.adin | upd7810.adrange)
1664 			{
1665 				case 0: upd7810.tmpcr = an0_func(); break;
1666 				case 1: upd7810.tmpcr = an1_func(); break;
1667 				case 2: upd7810.tmpcr = an2_func(); break;
1668 				case 3: upd7810.tmpcr = an3_func(); break;
1669 				case 4: upd7810.tmpcr = an4_func(); break;
1670 				case 5: upd7810.tmpcr = an5_func(); break;
1671 				case 6: upd7810.tmpcr = an6_func(); break;
1672 				case 7: upd7810.tmpcr = an7_func(); break;
1673 			}
1674 			upd7810.shdone = 1;
1675 		}
1676 		if (upd7810.adcnt > upd7810.adtot)
1677 		{
1678 			upd7810.adcnt -= upd7810.adtot;
1679 			switch (upd7810.adout)
1680 			{
1681 				case 0: CR0 = upd7810.tmpcr ? 0xff:0x00; break;
1682 				case 1: CR1 = upd7810.tmpcr ? 0xff:0x00; break;
1683 				case 2: CR2 = upd7810.tmpcr ? 0xff:0x00; break;
1684 				case 3: CR3 = upd7810.tmpcr ? 0xff:0x00; break;
1685 			}
1686 			upd7810.adin  = (upd7810.adin  + 1) & 0x07;
1687 			upd7810.adout = (upd7810.adout + 1) & 0x03;
1688 			if (upd7810.adout == 0)
1689 				IRR |= INTFAD;
1690 			upd7810.shdone = 0;
1691 		}
1692 	}
1693 }
1694 
1695 #include "7810tbl.c"
1696 #include "7810ops.c"
1697 
fake_an_func()1698 static UINT8 fake_an_func()
1699 {
1700        return 0;
1701 }
1702 
upd7810SetAnfunc(INT32 select,UINT8 (* func)())1703 void upd7810SetAnfunc(INT32 select, UINT8 (*func)())
1704 {
1705        switch (select & 7)
1706        {
1707                case 0: an0_func = func; break;
1708                case 1: an1_func = func; break;
1709                case 2: an2_func = func; break;
1710                case 3: an3_func = func; break;
1711                case 4: an4_func = func; break;
1712                case 5: an5_func = func; break;
1713                case 6: an6_func = func; break;
1714                case 7: an7_func = func; break;
1715        }
1716 }
1717 
upd7810Open(INT32)1718 void upd7810Open(INT32)
1719 {
1720 	// only one CPU supported
1721 }
1722 
upd7810Close()1723 void upd7810Close()
1724 {
1725 
1726 }
1727 
upd7810GetActive()1728 INT32 upd7810GetActive()
1729 {
1730 	return 0; // only one cpu supported
1731 }
1732 
upd7810_init(INT32 (* io_callback)(INT32 ioline,INT32 state))1733 static void upd7810_init(INT32 (*io_callback)(INT32 ioline, INT32 state))
1734 {
1735 	upd7810_io_callback = io_callback;
1736 
1737 	read_byte_8 = dummy_read;
1738 	write_byte_8 = dummy_write;
1739 	io_read_byte_8 = dummy_read_port;
1740 	io_write_byte_8 = dummy_write_port;
1741 
1742 	memset (mem, 0, 3 * 0x100 * sizeof(UINT8*));
1743 
1744 	an0_func = fake_an_func;
1745 	an1_func = fake_an_func;
1746 	an2_func = fake_an_func;
1747 	an3_func = fake_an_func;
1748 	an4_func = fake_an_func;
1749 	an5_func = fake_an_func;
1750 	an6_func = fake_an_func;
1751 	an7_func = fake_an_func;
1752 
1753 	CpuCheatRegister(0, &upd7810Config);
1754 
1755 #if 0
1756 	int cpu = cpu_getactivecpu();
1757 
1758 	state_save_register_UINT16("upd7810", cpu, "ppc", &upd7810.ppc.w.l, 1);
1759 	state_save_register_UINT16("upd7810", cpu, "pc", &upd7810.pc.w.l, 1);
1760 	state_save_register_UINT16("upd7810", cpu, "sp", &upd7810.sp.w.l, 1);
1761 	state_save_register_UINT8 ("upd7810", cpu, "psw", &upd7810.psw, 1);
1762 	state_save_register_UINT8 ("upd7810", cpu, "op", &upd7810.op, 1);
1763 	state_save_register_UINT8 ("upd7810", cpu, "op2", &upd7810.op2, 1);
1764 	state_save_register_UINT8 ("upd7810", cpu, "iff", &upd7810.iff, 1);
1765 	state_save_register_UINT16("upd7810", cpu, "ea", &upd7810.ea.w.l, 1);
1766 	state_save_register_UINT16("upd7810", cpu, "va", &upd7810.va.w.l, 1);
1767 	state_save_register_UINT16("upd7810", cpu, "bc", &upd7810.bc.w.l, 1);
1768 	state_save_register_UINT16("upd7810", cpu, "de", &upd7810.de.w.l, 1);
1769 	state_save_register_UINT16("upd7810", cpu, "hl", &upd7810.hl.w.l, 1);
1770 	state_save_register_UINT16("upd7810", cpu, "ea2", &upd7810.ea2.w.l, 1);
1771 	state_save_register_UINT16("upd7810", cpu, "va2", &upd7810.va2.w.l, 1);
1772 	state_save_register_UINT16("upd7810", cpu, "bc2", &upd7810.bc2.w.l, 1);
1773 	state_save_register_UINT16("upd7810", cpu, "de2", &upd7810.de2.w.l, 1);
1774 	state_save_register_UINT16("upd7810", cpu, "hl2", &upd7810.hl2.w.l, 1);
1775 	state_save_register_UINT32("upd7810", cpu, "cnt", &upd7810.cnt.d, 1);
1776 	state_save_register_UINT32("upd7810", cpu, "tm", &upd7810.tm.d, 1);
1777 	state_save_register_UINT32("upd7810", cpu, "ecnt", &upd7810.ecnt.d, 1);
1778 	state_save_register_UINT32("upd7810", cpu, "etm", &upd7810.etm.d, 1);
1779 	state_save_register_UINT8 ("upd7810", cpu, "ma", &upd7810.ma, 1);
1780 	state_save_register_UINT8 ("upd7810", cpu, "mb", &upd7810.mb, 1);
1781 	state_save_register_UINT8 ("upd7810", cpu, "mcc", &upd7810.mcc, 1);
1782 	state_save_register_UINT8 ("upd7810", cpu, "mc", &upd7810.mc, 1);
1783 	state_save_register_UINT8 ("upd7810", cpu, "mm", &upd7810.mm, 1);
1784 	state_save_register_UINT8 ("upd7810", cpu, "mf", &upd7810.mf, 1);
1785 	state_save_register_UINT8 ("upd7810", cpu, "tmm", &upd7810.tmm, 1);
1786 	state_save_register_UINT8 ("upd7810", cpu, "etmm", &upd7810.etmm, 1);
1787 	state_save_register_UINT8 ("upd7810", cpu, "eom", &upd7810.eom, 1);
1788 	state_save_register_UINT8 ("upd7810", cpu, "sml", &upd7810.sml, 1);
1789 	state_save_register_UINT8 ("upd7810", cpu, "smh", &upd7810.smh, 1);
1790 	state_save_register_UINT8 ("upd7810", cpu, "anm", &upd7810.anm, 1);
1791 	state_save_register_UINT8 ("upd7810", cpu, "mkl", &upd7810.mkl, 1);
1792 	state_save_register_UINT8 ("upd7810", cpu, "mkh", &upd7810.mkh, 1);
1793 	state_save_register_UINT8 ("upd7810", cpu, "zcm", &upd7810.zcm, 1);
1794 	state_save_register_UINT8 ("upd7810", cpu, "pa_out", &upd7810.pa_out, 1);
1795 	state_save_register_UINT8 ("upd7810", cpu, "pb_out", &upd7810.pb_out, 1);
1796 	state_save_register_UINT8 ("upd7810", cpu, "pc_out", &upd7810.pc_out, 1);
1797 	state_save_register_UINT8 ("upd7810", cpu, "pd_out", &upd7810.pd_out, 1);
1798 	state_save_register_UINT8 ("upd7810", cpu, "pf_out", &upd7810.pf_out, 1);
1799 	state_save_register_UINT8 ("upd7810", cpu, "cr0", &upd7810.cr0, 1);
1800 	state_save_register_UINT8 ("upd7810", cpu, "cr1", &upd7810.cr1, 1);
1801 	state_save_register_UINT8 ("upd7810", cpu, "cr2", &upd7810.cr2, 1);
1802 	state_save_register_UINT8 ("upd7810", cpu, "cr3", &upd7810.cr3, 1);
1803 	state_save_register_UINT8 ("upd7810", cpu, "txb", &upd7810.txb, 1);
1804 	state_save_register_UINT8 ("upd7810", cpu, "rxb", &upd7810.rxb, 1);
1805 	state_save_register_UINT8 ("upd7810", cpu, "txd", &upd7810.txd, 1);
1806 	state_save_register_UINT8 ("upd7810", cpu, "rxd", &upd7810.rxd, 1);
1807 	state_save_register_UINT8 ("upd7810", cpu, "sck", &upd7810.sck, 1);
1808 	state_save_register_UINT8 ("upd7810", cpu, "ti", &upd7810.ti, 1);
1809 	state_save_register_UINT8 ("upd7810", cpu, "to", &upd7810.to, 1);
1810 	state_save_register_UINT8 ("upd7810", cpu, "ci", &upd7810.ci, 1);
1811 	state_save_register_UINT8 ("upd7810", cpu, "co0", &upd7810.co0, 1);
1812 	state_save_register_UINT8 ("upd7810", cpu, "co1", &upd7810.co1, 1);
1813 	state_save_register_UINT16("upd7810", cpu, "irr", &upd7810.irr, 1);
1814 	state_save_register_UINT16("upd7810", cpu, "itf", &upd7810.itf, 1);
1815 	state_save_register_INT32 ("upd7810", cpu, "ovc0", &upd7810.ovc0, 1);
1816 	state_save_register_INT32 ("upd7810", cpu, "ovc1", &upd7810.ovc1, 1);
1817 	state_save_register_INT32 ("upd7810", cpu, "ovcf", &upd7810.ovcf, 1);
1818 	state_save_register_INT32 ("upd7810", cpu, "ovcs", &upd7810.ovcs, 1);
1819 	state_save_register_UINT8 ("upd7810", cpu, "edges",&upd7810.edges,1);
1820 #endif
1821 }
1822 
upd7810Scan(INT32 nAction)1823 INT32 upd7810Scan(INT32 nAction)
1824 {
1825 	struct BurnArea ba;
1826 
1827 	if (nAction & ACB_DRIVER_DATA)
1828 	{
1829 		ba.Data		= &upd7810;
1830 		ba.nLen		= sizeof(upd7810);
1831 		ba.nAddress = 0;
1832 		ba.szName	= "Upd7810 Regs";
1833 		BurnAcb(&ba);
1834 
1835 		SCAN_VAR(upd7810_icount);
1836 		SCAN_VAR(upd7810_total_cycles);
1837 		SCAN_VAR(upd7810_current_cycles);
1838 	}
1839 
1840 	return 0;
1841 }
1842 
upd7810Init(INT32 (* io_callback)(INT32 ioline,INT32 state))1843 void upd7810Init(INT32 (*io_callback)(INT32 ioline, INT32 state))
1844 {
1845 	upd7810_init(io_callback);
1846 
1847 	opXX = opXX_7810;
1848 
1849 }
1850 
upd7807Init(INT32 (* io_callback)(INT32 ioline,INT32 state))1851 void upd7807Init(INT32 (*io_callback)(INT32 ioline, INT32 state))
1852 {
1853 	upd7810_init(io_callback);
1854 
1855 	opXX = opXX_7807;
1856 
1857 }
1858 
upd7810Reset()1859 void upd7810Reset()
1860 {
1861 	memset(&upd7810, 0, sizeof(upd7810));
1862 	MA = 0xff;
1863 	MB = 0xff;
1864 	MC = 0xff;
1865 
1866 	MF = 0xff;
1867 	TMM = 0xff;
1868 	ETMM = 0xff;
1869 	// gamemaster falling block "and"s to enable interrupts
1870 	MKL = 0xff;
1871 	MKH = 0xff; //?
1872 
1873 	upd7810_icount = 0;
1874 	upd7810_total_cycles = 0;
1875 	upd7810_current_cycles = 0;
1876 
1877 	upd7810.PANM = 0xff; //reset
1878 }
1879 
upd7810Exit()1880 void upd7810Exit()
1881 {
1882 	upd7810_io_callback = NULL;
1883 	upd7810_config_type = 0;
1884 }
1885 
1886 static int run_end = 0;
1887 
upd7810Run(INT32 cycles)1888 INT32 upd7810Run(INT32 cycles)
1889 {
1890 	upd7810_current_cycles = cycles;
1891 	upd7810_icount = cycles;
1892 
1893 	run_end = 0;
1894 
1895 	do
1896 	{
1897 		int cc = 0;
1898 
1899 #if 0
1900 		CALL_MAME_DEBUG;
1901 #endif
1902 		PPC = PC;
1903 
1904 		RDOP(OP);
1905 
1906 		/*
1907          * clear L0 and/or L1 flags for all opcodes except
1908          * L0   for "MVI L,xx" or "LXI H,xxxx"
1909          * L1   for "MVI A,xx"
1910          */
1911 		PSW &= ~opXX[OP].mask_l0_l1;
1912 
1913 		/* skip flag set and not SOFTI opcode? */
1914 		if ((PSW & SK) && (OP != 0x72))
1915 		{
1916 			if (opXX[OP].cycles)
1917 			{
1918 				cc = opXX[OP].cycles_skip;
1919 				PC += opXX[OP].oplen - 1;
1920 			}
1921 			else
1922 			{
1923 				RDOP(OP2);
1924 
1925 				switch (OP)
1926 				{
1927 				case 0x48:
1928 					cc = op48[OP2].cycles_skip;
1929 					PC += op48[OP2].oplen - 2;
1930 					break;
1931 				case 0x4c:
1932 					cc = op4C[OP2].cycles_skip;
1933 					PC += op4C[OP2].oplen - 2;
1934 					break;
1935 				case 0x4d:
1936 					cc = op4D[OP2].cycles_skip;
1937 					PC += op4D[OP2].oplen - 2;
1938 					break;
1939 				case 0x60:
1940 					cc = op60[OP2].cycles_skip;
1941 					PC += op60[OP2].oplen - 2;
1942 					break;
1943 				case 0x64:
1944 					cc = op64[OP2].cycles_skip;
1945 					PC += op64[OP2].oplen - 2;
1946 					break;
1947 				case 0x70:
1948 					cc = op70[OP2].cycles_skip;
1949 					PC += op70[OP2].oplen - 2;
1950 					break;
1951 				case 0x74:
1952 					cc = op74[OP2].cycles_skip;
1953 					PC += op74[OP2].oplen - 2;
1954 					break;
1955 				//default:
1956 				//	osd_die("uPD7810 internal error: check cycle counts for main\n");
1957 				}
1958 			}
1959 
1960 			PSW &= ~SK;
1961 			upd7810_timers( cc );
1962 			//change_pc( PCD );
1963 		}
1964 		else
1965 		{
1966 			cc = opXX[OP].cycles;
1967 			upd7810_timers( cc );
1968 			(*opXX[OP].opfunc)();
1969 		}
1970 
1971 		upd7810_icount -= cc;
1972 		upd7810_take_irq();
1973 
1974 		if (run_end) {
1975 			run_end = 0;
1976 			break;
1977 		}
1978 	} while (upd7810_icount > 0);
1979 
1980 	upd7810_total_cycles += (upd7810_current_cycles - upd7810_icount);
1981 
1982 	INT32 ret = cycles - upd7810_icount;
1983 
1984 	upd7810_current_cycles = 0;
1985 	upd7810_icount = 0;
1986 
1987 	return ret;
1988 }
1989 
upd7810TotalCycles()1990 INT32 upd7810TotalCycles()
1991 {
1992 	return upd7810_total_cycles + (upd7810_current_cycles - upd7810_icount);
1993 }
1994 
upd7810NewFrame()1995 void upd7810NewFrame()
1996 {
1997 	upd7810_total_cycles = 0;
1998 	upd7810_current_cycles = 0;
1999 	upd7810_icount = 0;
2000 }
2001 
upd7810RunEnd()2002 void upd7810RunEnd()
2003 {
2004 	run_end = 1;
2005 }
2006 
upd7810Idle(INT32 cycles)2007 INT32 upd7810Idle(INT32 cycles)
2008 {
2009 	upd7810_total_cycles += cycles;
2010 	return cycles;
2011 }
2012 
2013 #if 0
2014 static void upd7810_get_context (void *dst)
2015 {
2016 	if (dst)
2017 		memcpy(dst, &upd7810, sizeof(upd7810));
2018 }
2019 
2020 static void upd7810_set_context (void *src)
2021 {
2022 	if (src)
2023 		memcpy(&upd7810, src, sizeof(upd7810));
2024 }
2025 #endif
2026 
2027 // if probs with taito c-chip, add the edge level checks hereunder in latest upd7810 core
set_irq_line(int irqline,int state)2028 static void set_irq_line(int irqline, int state)
2029 {
2030 	if (state != CLEAR_LINE)
2031 	{
2032 		if (irqline == CPU_IRQLINE_NMI)
2033 		{
2034 			/* no nested NMIs ? */
2035 //          if (0 == (IRR & INTNMI))
2036 			{
2037 	            IRR |= INTNMI;
2038 			}
2039 		}
2040 		else
2041 		if (irqline == UPD7810_INTF1)
2042 			IRR |= INTF1;
2043 		else
2044 		if (irqline == UPD7810_INTF2)
2045 			IRR |= INTF2;
2046 		// gamemaster hack
2047 		else
2048 		if (irqline == UPD7810_INTFE1)
2049 			IRR |= INTFE1;
2050 	//	else
2051 	//		logerror("upd7810_set_irq_line invalid irq line #%d\n", irqline);
2052 	}
2053 	/* resetting interrupt requests is done with the SKIT/SKNIT opcodes only! */
2054 }
2055 
upd7810SetIRQLine(INT32 line,INT32 state)2056 void upd7810SetIRQLine(INT32 line, INT32 state)
2057 {
2058 	if (state == CPU_IRQSTATUS_AUTO)
2059 	{
2060 		set_irq_line(line, 1);
2061 		upd7810Run(10);
2062 		set_irq_line(line, 0);
2063 
2064 	}
2065 	else
2066 	{
2067 		set_irq_line(line, state);
2068 		//upd7810Run(10);
2069 	}
2070 }
2071 
2072 #if 0
2073 
2074 static offs_t upd7810_dasm(char *buffer, offs_t pc)
2075 {
2076 #ifdef MAME_DEBUG
2077 	return Dasm7810( buffer, pc );
2078 #else
2079 	UINT8 op = cpu_readop(pc);
2080 	sprintf( buffer, "$%02X", op );
2081 	return 1;
2082 #endif
2083 }
2084 
2085 
2086 static offs_t upd7807_dasm(char *buffer, offs_t pc)
2087 {
2088 #ifdef MAME_DEBUG
2089 	return Dasm7807( buffer, pc );
2090 #else
2091 	UINT8 op = cpu_readop(pc);
2092 	sprintf( buffer, "$%02X", op );
2093 	return 1;
2094 #endif
2095 }
2096 
2097 
2098 /**************************************************************************
2099  * Generic set_info
2100  **************************************************************************/
2101 
2102 static void upd7810_set_info(UINT32 state, union cpuinfo *info)
2103 {
2104 	switch (state)
2105 	{
2106 		/* --- the following bits of info are set as 64-bit signed integers --- */
2107 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	set_irq_line(INPUT_LINE_NMI, info->i);	break;
2108 		case CPUINFO_INT_INPUT_STATE + UPD7810_INTF1:	set_irq_line(UPD7810_INTF1, info->i);	break;
2109 		case CPUINFO_INT_INPUT_STATE + UPD7810_INTF2:	set_irq_line(UPD7810_INTF2, info->i);	break;
2110 		case CPUINFO_INT_INPUT_STATE + UPD7810_INTFE1:	set_irq_line(UPD7810_INTFE1, info->i);	break;
2111 
2112 		case CPUINFO_INT_PC:							PC = info->i; change_pc(PCD);			break;
2113 		case CPUINFO_INT_REGISTER + UPD7810_PC:			PC = info->i; 							break;
2114 		case CPUINFO_INT_SP:
2115 		case CPUINFO_INT_REGISTER + UPD7810_SP:			SP = info->i; 							break;
2116 		case CPUINFO_INT_REGISTER + UPD7810_PSW:		PSW = info->i; 							break;
2117 		case CPUINFO_INT_REGISTER + UPD7810_A:			A = info->i; 							break;
2118 		case CPUINFO_INT_REGISTER + UPD7810_V:			V = info->i; 							break;
2119 		case CPUINFO_INT_REGISTER + UPD7810_EA:			EA = info->i; 							break;
2120 		case CPUINFO_INT_REGISTER + UPD7810_VA:			VA = info->i; 							break;
2121 		case CPUINFO_INT_REGISTER + UPD7810_BC:			BC = info->i; 							break;
2122 		case CPUINFO_INT_REGISTER + UPD7810_DE:			DE = info->i; 							break;
2123 		case CPUINFO_INT_REGISTER + UPD7810_HL:			HL = info->i; 							break;
2124 		case CPUINFO_INT_REGISTER + UPD7810_EA2:		EA2 = info->i; 							break;
2125 		case CPUINFO_INT_REGISTER + UPD7810_VA2:		VA2 = info->i; 							break;
2126 		case CPUINFO_INT_REGISTER + UPD7810_BC2:		BC2 = info->i; 							break;
2127 		case CPUINFO_INT_REGISTER + UPD7810_DE2:		DE2 = info->i; 							break;
2128 		case CPUINFO_INT_REGISTER + UPD7810_HL2:		HL2 = info->i; 							break;
2129 		case CPUINFO_INT_REGISTER + UPD7810_CNT0:		CNT0 = info->i; 						break;
2130 		case CPUINFO_INT_REGISTER + UPD7810_CNT1:		CNT1 = info->i; 						break;
2131 		case CPUINFO_INT_REGISTER + UPD7810_TM0:		TM0 = info->i; 							break;
2132 		case CPUINFO_INT_REGISTER + UPD7810_TM1:		TM1 = info->i; 							break;
2133 		case CPUINFO_INT_REGISTER + UPD7810_ECNT:		ECNT = info->i; 						break;
2134 		case CPUINFO_INT_REGISTER + UPD7810_ECPT:		ECPT = info->i; 						break;
2135 		case CPUINFO_INT_REGISTER + UPD7810_ETM0:		ETM0 = info->i; 						break;
2136 		case CPUINFO_INT_REGISTER + UPD7810_ETM1:		ETM1 = info->i; 						break;
2137 		case CPUINFO_INT_REGISTER + UPD7810_MA:			MA = info->i; 							break;
2138 		case CPUINFO_INT_REGISTER + UPD7810_MB:			MB = info->i; 							break;
2139 		case CPUINFO_INT_REGISTER + UPD7810_MCC:		MCC = info->i; 							break;
2140 		case CPUINFO_INT_REGISTER + UPD7810_MC:			MC = info->i; 							break;
2141 		case CPUINFO_INT_REGISTER + UPD7810_MM:			MM = info->i; 							break;
2142 		case CPUINFO_INT_REGISTER + UPD7810_MF:			MF = info->i; 							break;
2143 		case CPUINFO_INT_REGISTER + UPD7810_TMM:		TMM = info->i; 							break;
2144 		case CPUINFO_INT_REGISTER + UPD7810_ETMM:		ETMM = info->i; 						break;
2145 		case CPUINFO_INT_REGISTER + UPD7810_EOM:		EOM = info->i; 							break;
2146 		case CPUINFO_INT_REGISTER + UPD7810_SML:		SML = info->i; 							break;
2147 		case CPUINFO_INT_REGISTER + UPD7810_SMH:		SMH = info->i; 							break;
2148 		case CPUINFO_INT_REGISTER + UPD7810_ANM:		ANM = info->i; 							break;
2149 		case CPUINFO_INT_REGISTER + UPD7810_MKL:		MKL = info->i; 							break;
2150 		case CPUINFO_INT_REGISTER + UPD7810_MKH:		MKH = info->i; 							break;
2151 		case CPUINFO_INT_REGISTER + UPD7810_ZCM:		ZCM = info->i; 							break;
2152 		case CPUINFO_INT_REGISTER + UPD7810_TXB:		TXB = info->i; 							break;
2153 		case CPUINFO_INT_REGISTER + UPD7810_RXB:		RXB = info->i; 							break;
2154 		case CPUINFO_INT_REGISTER + UPD7810_CR0:		CR0 = info->i; 							break;
2155 		case CPUINFO_INT_REGISTER + UPD7810_CR1:		CR1 = info->i; 							break;
2156 		case CPUINFO_INT_REGISTER + UPD7810_CR2:		CR2 = info->i; 							break;
2157 		case CPUINFO_INT_REGISTER + UPD7810_CR3:		CR3 = info->i; 							break;
2158 		case CPUINFO_INT_REGISTER + UPD7810_TXD:		TXD = info->i; 							break;
2159 		case CPUINFO_INT_REGISTER + UPD7810_RXD:		RXD = info->i; 							break;
2160 		case CPUINFO_INT_REGISTER + UPD7810_SCK:		SCK = info->i; 							break;
2161 		case CPUINFO_INT_REGISTER + UPD7810_TI:			TI	= info->i; 							break;
2162 		case CPUINFO_INT_REGISTER + UPD7810_TO:			TO	= info->i; 							break;
2163 		case CPUINFO_INT_REGISTER + UPD7810_CI:			CI	= info->i; 							break;
2164 		case CPUINFO_INT_REGISTER + UPD7810_CO0:		CO0 = info->i; 							break;
2165 		case CPUINFO_INT_REGISTER + UPD7810_CO1:		CO1 = info->i; 							break;
2166 
2167 		/* --- the following bits of info are set as pointers to data or functions --- */
2168 		case CPUINFO_PTR_IRQ_CALLBACK:					upd7810.irq_callback = info->irqcallback; break;
2169 	}
2170 }
2171 
2172 
2173 
2174 /**************************************************************************
2175  * Generic get_info
2176  **************************************************************************/
2177 
2178 void upd7810_get_info(UINT32 state, union cpuinfo *info)
2179 {
2180 	switch (state)
2181 	{
2182 		/* --- the following bits of info are returned as 64-bit signed integers --- */
2183 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(upd7810);				break;
2184 		case CPUINFO_INT_INPUT_LINES:					info->i = 2;							break;
2185 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
2186 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
2187 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
2188 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
2189 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 4;							break;
2190 		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
2191 		case CPUINFO_INT_MAX_CYCLES:					info->i = 40;							break;
2192 
2193 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
2194 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16;					break;
2195 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
2196 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
2197 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
2198 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
2199 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
2200 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 8;					break;
2201 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
2202 
2203 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	info->i = (IRR & INTNMI) ? ASSERT_LINE : CLEAR_LINE; break;
2204 		case CPUINFO_INT_INPUT_STATE + UPD7810_INTF1:	info->i = (IRR & INTF1) ? ASSERT_LINE : CLEAR_LINE; break;
2205 		case CPUINFO_INT_INPUT_STATE + UPD7810_INTF2:	info->i = (IRR & INTF2) ? ASSERT_LINE : CLEAR_LINE; break;
2206 		case CPUINFO_INT_INPUT_STATE + UPD7810_INTFE1:	info->i = (IRR & INTFE1) ? ASSERT_LINE : CLEAR_LINE; break;
2207 
2208 		case CPUINFO_INT_PREVIOUSPC:					info->i = PPC;							break;
2209 
2210 		case CPUINFO_INT_PC:
2211 		case CPUINFO_INT_REGISTER + UPD7810_PC:			info->i = PC;							break;
2212 		case CPUINFO_INT_SP:
2213 		case CPUINFO_INT_REGISTER + UPD7810_SP:			info->i = SP;							break;
2214 		case CPUINFO_INT_REGISTER + UPD7810_PSW:		info->i = PSW;							break;
2215 		case CPUINFO_INT_REGISTER + UPD7810_EA:			info->i = EA;							break;
2216 		case CPUINFO_INT_REGISTER + UPD7810_VA:			info->i = VA;							break;
2217 		case CPUINFO_INT_REGISTER + UPD7810_BC:			info->i = BC;							break;
2218 		case CPUINFO_INT_REGISTER + UPD7810_DE:			info->i = DE;							break;
2219 		case CPUINFO_INT_REGISTER + UPD7810_HL:			info->i = HL;							break;
2220 		case CPUINFO_INT_REGISTER + UPD7810_EA2:		info->i = EA2;							break;
2221 		case CPUINFO_INT_REGISTER + UPD7810_VA2:		info->i = VA2;							break;
2222 		case CPUINFO_INT_REGISTER + UPD7810_BC2:		info->i = BC2;							break;
2223 		case CPUINFO_INT_REGISTER + UPD7810_DE2:		info->i = DE2;							break;
2224 		case CPUINFO_INT_REGISTER + UPD7810_HL2:		info->i = HL2;							break;
2225 		case CPUINFO_INT_REGISTER + UPD7810_CNT0:		info->i = CNT0;							break;
2226 		case CPUINFO_INT_REGISTER + UPD7810_CNT1:		info->i = CNT1;							break;
2227 		case CPUINFO_INT_REGISTER + UPD7810_TM0:		info->i = TM0;							break;
2228 		case CPUINFO_INT_REGISTER + UPD7810_TM1:		info->i = TM1;							break;
2229 		case CPUINFO_INT_REGISTER + UPD7810_ECNT:		info->i = ECNT;							break;
2230 		case CPUINFO_INT_REGISTER + UPD7810_ECPT:		info->i = ECPT;							break;
2231 		case CPUINFO_INT_REGISTER + UPD7810_ETM0:		info->i = ETM0;							break;
2232 		case CPUINFO_INT_REGISTER + UPD7810_ETM1:		info->i = ETM1;							break;
2233 		case CPUINFO_INT_REGISTER + UPD7810_MA:			info->i = MA;							break;
2234 		case CPUINFO_INT_REGISTER + UPD7810_MB:			info->i = MB;							break;
2235 		case CPUINFO_INT_REGISTER + UPD7810_MCC:		info->i = MCC;							break;
2236 		case CPUINFO_INT_REGISTER + UPD7810_MC:			info->i = MC;							break;
2237 		case CPUINFO_INT_REGISTER + UPD7810_MM:			info->i = MM;							break;
2238 		case CPUINFO_INT_REGISTER + UPD7810_MF:			info->i = MF;							break;
2239 		case CPUINFO_INT_REGISTER + UPD7810_TMM:		info->i = TMM;							break;
2240 		case CPUINFO_INT_REGISTER + UPD7810_ETMM:		info->i = ETMM;							break;
2241 		case CPUINFO_INT_REGISTER + UPD7810_EOM:		info->i = EOM;							break;
2242 		case CPUINFO_INT_REGISTER + UPD7810_SML:		info->i = SML;							break;
2243 		case CPUINFO_INT_REGISTER + UPD7810_SMH:		info->i = SMH;							break;
2244 		case CPUINFO_INT_REGISTER + UPD7810_ANM:		info->i = ANM;							break;
2245 		case CPUINFO_INT_REGISTER + UPD7810_MKL:		info->i = MKL;							break;
2246 		case CPUINFO_INT_REGISTER + UPD7810_MKH:		info->i = MKH;							break;
2247 		case CPUINFO_INT_REGISTER + UPD7810_ZCM:		info->i = ZCM;							break;
2248 		case CPUINFO_INT_REGISTER + UPD7810_TXB:		info->i = TXB;							break;
2249 		case CPUINFO_INT_REGISTER + UPD7810_RXB:		info->i = RXB;							break;
2250 		case CPUINFO_INT_REGISTER + UPD7810_CR0:		info->i = CR0;							break;
2251 		case CPUINFO_INT_REGISTER + UPD7810_CR1:		info->i = CR1;							break;
2252 		case CPUINFO_INT_REGISTER + UPD7810_CR2:		info->i = CR2;							break;
2253 		case CPUINFO_INT_REGISTER + UPD7810_CR3:		info->i = CR3;							break;
2254 		case CPUINFO_INT_REGISTER + UPD7810_TXD:		info->i = TXD;							break;
2255 		case CPUINFO_INT_REGISTER + UPD7810_RXD:		info->i = RXD;							break;
2256 		case CPUINFO_INT_REGISTER + UPD7810_SCK:		info->i = SCK;							break;
2257 		case CPUINFO_INT_REGISTER + UPD7810_TI:			info->i = TI;							break;
2258 		case CPUINFO_INT_REGISTER + UPD7810_TO:			info->i = TO;							break;
2259 		case CPUINFO_INT_REGISTER + UPD7810_CI:			info->i = CI;							break;
2260 		case CPUINFO_INT_REGISTER + UPD7810_CO0:		info->i = CO0;							break;
2261 		case CPUINFO_INT_REGISTER + UPD7810_CO1:		info->i = CO1;							break;
2262 
2263 		/* --- the following bits of info are returned as pointers to data or functions --- */
2264 		case CPUINFO_PTR_SET_INFO:						info->setinfo = upd7810_set_info;		break;
2265 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = upd7810_get_context;	break;
2266 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = upd7810_set_context;	break;
2267 		case CPUINFO_PTR_INIT:							info->init = upd7810_init;				break;
2268 		case CPUINFO_PTR_RESET:							info->reset = upd7810_reset;			break;
2269 		case CPUINFO_PTR_EXIT:							info->exit = upd7810_exit;				break;
2270 		case CPUINFO_PTR_EXECUTE:						info->execute = upd7810_execute;		break;
2271 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
2272 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = upd7810_dasm;		break;
2273 		case CPUINFO_PTR_IRQ_CALLBACK:					info->irqcallback = upd7810.irq_callback; break;
2274 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &upd7810_icount;			break;
2275 		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = upd7810_reg_layout;			break;
2276 		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = upd7810_win_layout;			break;
2277 
2278 		/* --- the following bits of info are returned as NULL-terminated strings --- */
2279 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "uPD7810"); break;
2280 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "NEC uPD7810"); break;
2281 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s = cpuintrf_temp_str(), "0.3"); break;
2282 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s = cpuintrf_temp_str(), __FILE__); break;
2283 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s = cpuintrf_temp_str(), "Copyright (c) 2001 Juergen Buchmueller, all rights reserved."); break;
2284 
2285 		case CPUINFO_STR_FLAGS:
2286 			sprintf(info->s = cpuintrf_temp_str(), "%s:%s:%s:%s:%s:%s",
2287 				upd7810.psw & 0x40 ? "ZF":"--",
2288 				upd7810.psw & 0x20 ? "SK":"--",
2289 				upd7810.psw & 0x10 ? "HC":"--",
2290 				upd7810.psw & 0x08 ? "L1":"--",
2291 				upd7810.psw & 0x04 ? "L0":"--",
2292 				upd7810.psw & 0x01 ? "CY":"--");
2293 			break;
2294 
2295 		case CPUINFO_STR_REGISTER + UPD7810_PC:			sprintf(info->s = cpuintrf_temp_str(), "PC  :%04X", upd7810.pc.w.l); break;
2296 		case CPUINFO_STR_REGISTER + UPD7810_SP:			sprintf(info->s = cpuintrf_temp_str(), "SP  :%04X", upd7810.sp.w.l); break;
2297 		case CPUINFO_STR_REGISTER + UPD7810_PSW:		sprintf(info->s = cpuintrf_temp_str(), "PSW :%02X", upd7810.psw); break;
2298 		case CPUINFO_STR_REGISTER + UPD7810_A:			sprintf(info->s = cpuintrf_temp_str(), "A   :%02X", upd7810.va.b.l); break;
2299 		case CPUINFO_STR_REGISTER + UPD7810_V:			sprintf(info->s = cpuintrf_temp_str(), "V   :%02X", upd7810.va.b.h); break;
2300 		case CPUINFO_STR_REGISTER + UPD7810_EA:			sprintf(info->s = cpuintrf_temp_str(), "EA  :%04X", upd7810.ea.w.l); break;
2301 		case CPUINFO_STR_REGISTER + UPD7810_BC:			sprintf(info->s = cpuintrf_temp_str(), "BC  :%04X", upd7810.bc.w.l); break;
2302 		case CPUINFO_STR_REGISTER + UPD7810_DE:			sprintf(info->s = cpuintrf_temp_str(), "DE  :%04X", upd7810.de.w.l); break;
2303 		case CPUINFO_STR_REGISTER + UPD7810_HL:			sprintf(info->s = cpuintrf_temp_str(), "HL  :%04X", upd7810.hl.w.l); break;
2304 		case CPUINFO_STR_REGISTER + UPD7810_A2:			sprintf(info->s = cpuintrf_temp_str(), "A'  :%02X", upd7810.va2.b.l); break;
2305 		case CPUINFO_STR_REGISTER + UPD7810_V2:			sprintf(info->s = cpuintrf_temp_str(), "V'  :%02X", upd7810.va2.b.h); break;
2306 		case CPUINFO_STR_REGISTER + UPD7810_EA2:		sprintf(info->s = cpuintrf_temp_str(), "EA' :%04X", upd7810.ea2.w.l); break;
2307 		case CPUINFO_STR_REGISTER + UPD7810_BC2:		sprintf(info->s = cpuintrf_temp_str(), "BC' :%04X", upd7810.bc2.w.l); break;
2308 		case CPUINFO_STR_REGISTER + UPD7810_DE2:		sprintf(info->s = cpuintrf_temp_str(), "DE' :%04X", upd7810.de2.w.l); break;
2309 		case CPUINFO_STR_REGISTER + UPD7810_HL2:		sprintf(info->s = cpuintrf_temp_str(), "HL' :%04X", upd7810.hl2.w.l); break;
2310 		case CPUINFO_STR_REGISTER + UPD7810_CNT0:		sprintf(info->s = cpuintrf_temp_str(), "CNT0:%02X", upd7810.cnt.b.l); break;
2311 		case CPUINFO_STR_REGISTER + UPD7810_CNT1:		sprintf(info->s = cpuintrf_temp_str(), "CNT1:%02X", upd7810.cnt.b.h); break;
2312 		case CPUINFO_STR_REGISTER + UPD7810_TM0:		sprintf(info->s = cpuintrf_temp_str(), "TM0 :%02X", upd7810.tm.b.l); break;
2313 		case CPUINFO_STR_REGISTER + UPD7810_TM1:		sprintf(info->s = cpuintrf_temp_str(), "TM1 :%02X", upd7810.tm.b.h); break;
2314 		case CPUINFO_STR_REGISTER + UPD7810_ECNT:		sprintf(info->s = cpuintrf_temp_str(), "ECNT:%04X", upd7810.ecnt.w.l); break;
2315 		case CPUINFO_STR_REGISTER + UPD7810_ECPT:		sprintf(info->s = cpuintrf_temp_str(), "ECPT:%04X", upd7810.ecnt.w.h); break;
2316 		case CPUINFO_STR_REGISTER + UPD7810_ETM0:		sprintf(info->s = cpuintrf_temp_str(), "ETM0:%04X", upd7810.etm.w.l); break;
2317 		case CPUINFO_STR_REGISTER + UPD7810_ETM1:		sprintf(info->s = cpuintrf_temp_str(), "ETM1:%04X", upd7810.etm.w.h); break;
2318 		case CPUINFO_STR_REGISTER + UPD7810_MA:			sprintf(info->s = cpuintrf_temp_str(), "MA  :%02X", upd7810.ma); break;
2319 		case CPUINFO_STR_REGISTER + UPD7810_MB:			sprintf(info->s = cpuintrf_temp_str(), "MB  :%02X", upd7810.mb); break;
2320 		case CPUINFO_STR_REGISTER + UPD7810_MCC:		sprintf(info->s = cpuintrf_temp_str(), "MCC :%02X", upd7810.mcc); break;
2321 		case CPUINFO_STR_REGISTER + UPD7810_MC:			sprintf(info->s = cpuintrf_temp_str(), "MC  :%02X", upd7810.mc); break;
2322 		case CPUINFO_STR_REGISTER + UPD7810_MM:			sprintf(info->s = cpuintrf_temp_str(), "MM  :%02X", upd7810.mm); break;
2323 		case CPUINFO_STR_REGISTER + UPD7810_MF:			sprintf(info->s = cpuintrf_temp_str(), "MF  :%02X", upd7810.mf); break;
2324 		case CPUINFO_STR_REGISTER + UPD7810_TMM:		sprintf(info->s = cpuintrf_temp_str(), "TMM :%02X", upd7810.tmm); break;
2325 		case CPUINFO_STR_REGISTER + UPD7810_ETMM:		sprintf(info->s = cpuintrf_temp_str(), "ETMM:%02X", upd7810.etmm); break;
2326 		case CPUINFO_STR_REGISTER + UPD7810_EOM:		sprintf(info->s = cpuintrf_temp_str(), "EOM :%02X", upd7810.eom); break;
2327 		case CPUINFO_STR_REGISTER + UPD7810_SML:		sprintf(info->s = cpuintrf_temp_str(), "SML :%02X", upd7810.sml); break;
2328 		case CPUINFO_STR_REGISTER + UPD7810_SMH:		sprintf(info->s = cpuintrf_temp_str(), "SMH :%02X", upd7810.smh); break;
2329 		case CPUINFO_STR_REGISTER + UPD7810_ANM:		sprintf(info->s = cpuintrf_temp_str(), "ANM :%02X", upd7810.anm); break;
2330 		case CPUINFO_STR_REGISTER + UPD7810_MKL:		sprintf(info->s = cpuintrf_temp_str(), "MKL :%02X", upd7810.mkl); break;
2331 		case CPUINFO_STR_REGISTER + UPD7810_MKH:		sprintf(info->s = cpuintrf_temp_str(), "MKH :%02X", upd7810.mkh); break;
2332 		case CPUINFO_STR_REGISTER + UPD7810_ZCM:		sprintf(info->s = cpuintrf_temp_str(), "ZCM :%02X", upd7810.zcm); break;
2333 		case CPUINFO_STR_REGISTER + UPD7810_CR0:		sprintf(info->s = cpuintrf_temp_str(), "CR0 :%02X", upd7810.cr0); break;
2334 		case CPUINFO_STR_REGISTER + UPD7810_CR1:		sprintf(info->s = cpuintrf_temp_str(), "CR1 :%02X", upd7810.cr1); break;
2335 		case CPUINFO_STR_REGISTER + UPD7810_CR2:		sprintf(info->s = cpuintrf_temp_str(), "CR2 :%02X", upd7810.cr2); break;
2336 		case CPUINFO_STR_REGISTER + UPD7810_CR3:		sprintf(info->s = cpuintrf_temp_str(), "CR3 :%02X", upd7810.cr3); break;
2337 		case CPUINFO_STR_REGISTER + UPD7810_RXB:		sprintf(info->s = cpuintrf_temp_str(), "RXB :%02X", upd7810.rxb); break;
2338 		case CPUINFO_STR_REGISTER + UPD7810_TXB:		sprintf(info->s = cpuintrf_temp_str(), "TXB :%02X", upd7810.txb); break;
2339 		case CPUINFO_STR_REGISTER + UPD7810_TXD:		sprintf(info->s = cpuintrf_temp_str(), "TXD :%d", upd7810.txd); break;
2340 		case CPUINFO_STR_REGISTER + UPD7810_RXD:		sprintf(info->s = cpuintrf_temp_str(), "RXD :%d", upd7810.rxd); break;
2341 		case CPUINFO_STR_REGISTER + UPD7810_SCK:		sprintf(info->s = cpuintrf_temp_str(), "SCK :%d", upd7810.sck); break;
2342 		case CPUINFO_STR_REGISTER + UPD7810_TI:			sprintf(info->s = cpuintrf_temp_str(), "TI  :%d", upd7810.ti); break;
2343 		case CPUINFO_STR_REGISTER + UPD7810_TO:			sprintf(info->s = cpuintrf_temp_str(), "TO  :%d", upd7810.to); break;
2344 		case CPUINFO_STR_REGISTER + UPD7810_CI:			sprintf(info->s = cpuintrf_temp_str(), "CI  :%d", upd7810.ci); break;
2345 		case CPUINFO_STR_REGISTER + UPD7810_CO0:		sprintf(info->s = cpuintrf_temp_str(), "CO0 :%d", upd7810.co0 & 1); break;
2346 		case CPUINFO_STR_REGISTER + UPD7810_CO1:		sprintf(info->s = cpuintrf_temp_str(), "CO1 :%d", upd7810.co1 & 1); break;
2347 	}
2348 }
2349 
2350 
2351 /**************************************************************************
2352  * CPU-specific set_info
2353  **************************************************************************/
2354 
2355 void upd7807_get_info(UINT32 state, union cpuinfo *info)
2356 {
2357 	switch (state)
2358 	{
2359 		/* --- the following bits of info are returned as pointers to data or functions --- */
2360 		case CPUINFO_PTR_RESET:							info->reset = upd7807_reset;			break;
2361 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = upd7807_dasm;		break;
2362 
2363 		/* --- the following bits of info are returned as NULL-terminated strings --- */
2364 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "uPD7807"); break;
2365 
2366 		default:
2367 			upd7810_get_info(state, info);
2368 			break;
2369 	}
2370 }
2371 #endif
2372