1 /*** Glue Code (******************************************
2 
3 Glue code to hook up Retrocade's CCPU emulator to MAME's
4 architecture.  Really, it's not so bad!
5 
6 **********************************************************/
7 
8 #include "driver.h"
9 #include "ccpu.h"
10 
11 /* the MAME version of the CCPU registers */
12 typedef struct ccpuRegs
13 {
14     UINT16  accVal;
15     UINT16  cmpVal;
16     UINT8   pa0;
17     UINT8   cFlag;
18     UINT16  eRegPC;
19     UINT16  eRegA;
20     UINT16  eRegB;
21     UINT16  eRegI;
22     UINT16  eRegJ;
23     UINT8   eRegP;
24     UINT8   eCState;
25 } ccpuRegs;
26 
27 #define CCPU_FETCH(a) ((unsigned)cpu_readop(a))
28 #define CCPU_READPORT(a) (cpu_readport (a))
29 #define CCPU_WRITEPORT(a,v) (cpu_writeport (a,v))
30 
31 #define RAW_VECTORS 1
32 
33 /* this #define works around the naming conflict with the opcode_table
34    in cinedbg.c */
35 #define opcode_table _opcode_table
36 
37 /* This prototype was missing */
38 extern void CinemaVectorData (int fromx, int fromy, int tox, int toy, int color);
39 
40 int ccpu_ICount = 1000;
41 
42 
43 extern UINT16 ioSwitches;
44 extern UINT16 ioInputs;
45 
46 
ccpu_reset(void * param)47 void ccpu_reset(void *param)
48 {
49 	cineReset();
50 }
51 
ccpu_exit(void)52 void ccpu_exit(void)
53 {
54 	/* nothing to do ? */
55 }
56 
ccpu_execute(int cycles)57 int ccpu_execute(int cycles)
58 {
59 	int newCycles;
60 
61 	newCycles = cineExec(cycles);
62 	return newCycles;
63 }
64 
65 
ccpu_get_context(void * dst)66 unsigned ccpu_get_context(void *dst)
67 {
68     if( dst )
69     {
70         CONTEXTCCPU context;
71         ccpuRegs *Regs = (ccpuRegs *)dst;
72         cGetContext (&context);
73         Regs->accVal = context.accVal;
74         Regs->cmpVal = context.cmpVal;
75         Regs->pa0 = context.pa0;
76         Regs->cFlag = context.cFlag;
77         Regs->eRegPC = context.eRegPC;
78         Regs->eRegA = context.eRegA;
79         Regs->eRegB = context.eRegB;
80         Regs->eRegI = context.eRegI;
81         Regs->eRegJ = context.eRegJ;
82         Regs->eRegP = context.eRegP;
83         Regs->eCState = context.eCState;
84     }
85     return sizeof(ccpuRegs);
86 }
87 
88 
ccpu_set_context(void * src)89 void ccpu_set_context(void *src)
90 {
91 	if( src )
92 	{
93 		CONTEXTCCPU context;
94 		ccpuRegs *Regs = (ccpuRegs *)src;
95 		context.accVal = Regs->accVal;
96 		context.cmpVal = Regs->cmpVal;
97 		context.pa0 = Regs->pa0;
98 		context.cFlag = Regs->cFlag;
99 		context.eRegPC = Regs->eRegPC;
100 		context.eRegA = Regs->eRegA;
101 		context.eRegB = Regs->eRegB;
102 		context.eRegI = Regs->eRegI;
103 		context.eRegJ = Regs->eRegJ;
104 		context.eRegP = Regs->eRegP;
105 		context.eCState = (CINESTATE)Regs->eCState;
106 		cSetContext (&context);
107 	}
108 }
109 
110 
ccpu_get_pc(void)111 unsigned ccpu_get_pc(void)
112 {
113 	CONTEXTCCPU context;
114 
115 	cGetContext (&context);
116 	return context.eRegPC;
117 }
118 
ccpu_set_pc(unsigned val)119 void ccpu_set_pc(unsigned val)
120 {
121 	CONTEXTCCPU context;
122 
123 	cGetContext (&context);
124 	context.eRegPC = val;
125 	cSetContext (&context);
126 }
127 
ccpu_get_sp(void)128 unsigned ccpu_get_sp(void)
129 {
130 	CONTEXTCCPU context;
131 
132 	cGetContext (&context);
133 	return context.eRegP;	/* Is this a stack pointer? */
134 }
135 
ccpu_set_sp(unsigned val)136 void ccpu_set_sp(unsigned val)
137 {
138 	CONTEXTCCPU context;
139 
140 	cGetContext (&context);
141 	context.eRegP = val;   /* Is this a stack pointer? */
142 	cSetContext (&context);
143 }
144 
ccpu_get_reg(int regnum)145 unsigned ccpu_get_reg(int regnum)
146 {
147 	CONTEXTCCPU context;
148 	cGetContext (&context);
149 
150 	switch( regnum )
151 	{
152 		case CCPU_ACC: return context.accVal;
153 		case CCPU_CMP: return context.cmpVal;
154 		case CCPU_PA0: return context.pa0;
155 		case CCPU_CFLAG: return context.cFlag;
156 		case CCPU_PC: return context.eRegPC;
157 		case CCPU_A: return context.eRegA;
158 		case CCPU_B: return context.eRegB;
159 		case CCPU_I: return context.eRegI;
160 		case CCPU_J: return context.eRegJ;
161 		case CCPU_P: return context.eRegP;
162 		case CCPU_CSTATE: return context.eCState;
163 /* TODO: return contents of [SP + wordsize * (REG_SP_CONTENTS-regnum)] */
164 		default:
165 			if( regnum <= REG_SP_CONTENTS )
166 				return 0;
167 	}
168 	return 0;
169 }
170 
ccpu_set_reg(int regnum,unsigned val)171 void ccpu_set_reg(int regnum, unsigned val)
172 {
173 	CONTEXTCCPU context;
174 
175 	cGetContext (&context);
176 	switch( regnum )
177 	{
178 		case CCPU_ACC: context.accVal = val; break;
179 		case CCPU_CMP: context.cmpVal = val; break;
180 		case CCPU_PA0: context.pa0 = val; break;
181 		case CCPU_CFLAG: context.cFlag = val; break;
182 		case CCPU_PC: context.eRegPC = val; break;
183 		case CCPU_A: context.eRegA = val; break;
184 		case CCPU_B: context.eRegB = val; break;
185 		case CCPU_I: context.eRegI = val; break;
186 		case CCPU_J: context.eRegJ = val; break;
187 		case CCPU_P: context.eRegP = val; break;
188 		case CCPU_CSTATE: context.eCState = (CINESTATE)val; break;
189 /* TODO: set contents of [SP + wordsize * (REG_SP_CONTENTS-regnum)] */
190 		default:
191 			if( regnum <= REG_SP_CONTENTS )
192 			{
193 				unsigned offset = /* SP? + */ (REG_SP_CONTENTS-regnum);
194 				(void)offset;
195 			}
196     }
197 	cSetContext (&context);
198 }
199 
200 
ccpu_set_nmi_line(int state)201 void ccpu_set_nmi_line(int state)
202 {
203 	/* nothing to do */
204 }
205 
ccpu_set_irq_line(int irqline,int state)206 void ccpu_set_irq_line(int irqline, int state)
207 {
208 	/* nothing to do */
209 }
210 
ccpu_set_irq_callback(int (* callback)(int irqline))211 void ccpu_set_irq_callback(int (*callback)(int irqline))
212 {
213 	/* nothing to do */
214 }
215 
ccpu_info(void * context,int regnum)216 const char *ccpu_info(void *context, int regnum)
217 {
218     switch( regnum )
219 	{
220 		case CPU_INFO_NAME: return "CCPU";
221 		case CPU_INFO_FAMILY: return "Cinematronics CPU";
222 		case CPU_INFO_VERSION: return "1.0";
223 		case CPU_INFO_FILE: return __FILE__;
224 		case CPU_INFO_CREDITS: return "Copyright 1997/1998 Jeff Mitchell and the Retrocade Alliance\nCopyright 1997 Zonn Moore";
225     }
226 	return "";
227 
228 }
229 
230 /* TODO: hook up the disassembler */
ccpu_dasm(char * buffer,unsigned pc)231 unsigned ccpu_dasm(char *buffer, unsigned pc)
232 {
233     sprintf( buffer, "$%02X", cpu_readop(pc) );
234 	return 1;
235 }
236 
ccpu_Config(int jmi,int msize,int monitor)237 void ccpu_Config (int jmi, int msize, int monitor)
238 {
239 	cineSetJMI (jmi);
240 	cineSetMSize (msize);
241 	cineSetMonitor (monitor);
242 }
243 
244 
ccpu_SetInputs(int inputs,int switches)245 void ccpu_SetInputs(int inputs, int switches)
246 {
247 /*	ioInputs = inputs;
248 	ioSwitches = switches;*/
249 }
250 
251 
252 /* To do:
253   - make RAM external */
254 
255 
256 /*============================================================================================*
257 
258 	BELOW LIES THE CORE OF THE CCPU. THE CODE WAS KINDLY GIVEN TO MAME BY ZONN MOORE,
259 	JEFF MITCHELL, AND NEIL BRADLEY. I HAVE PRETTY HEAVILY CLEANED IT UP.
260 
261  *============================================================================================*/
262 
263 
264 /*
265  * cinecore.c, cinedbg.c, cineops.c -- Cinematronics game emulator
266  * copyright 1997/1998 Jeff Mitchell and the Retrocade Alliance
267  * copyright 1997 Zonn Moore
268  *
269  * This Cinematronics emulator may be freely used in any non-commercial
270  * venture, and is to be considered as under the Gnu Public Licence
271  * (GPL, copyleft). To avoid a huge deluge of email, I also allow the
272  * MAME team usage under the so-called MAME licence for non-commercial
273  * use.
274  *
275  * There are some restrictions, however, mostly to help further development
276  * of the emulator and continue the enjoyment these fine games have
277  * provided.
278  *
279  * 1) Jeff Mitchell (skeezix@skeleton.org) is the authoritative maintainer for
280  *    the C implementation of the "CCPU" written by Zonn Moore. Modifications
281  *    or changes to this code may not be distributed in source form, in whole
282  *    or in part, without the written permission of the maintainer. (ie: At
283  *    some point after changes have been made, submit them to the maintainer
284  *    for inclusion into the authoritative source tree, for all to use.)
285  * 2) Credit must be given where appropriate: Jeff Mitchell, author of the
286  *    C version. Zonn Moore for the ASM version and all original research,
287  *    original documentation, etc. (The C version is a rewrite of Zonn's
288  *    brilliant work.) Neil Bradley, for the 32bit conversion of the ASM
289  *    core, and technical assistance. Without him, the C version wouldn't
290  *    have been written. Where possible, please include references to the
291  *    official website for the software (see below), so that others may
292  *    easily find the sources.
293  * 3) Users of this software are encouraged to periodically check the
294  *    official website for new revisions, bugfixes, etc. This is an
295  *    ongoing project, with many optimizations yet to be done.
296  *
297  * Games known to work 100% or nearly so, at some point or another of
298  * the emulators development (but not necessarily right now :):
299  * RipOff, Solar Quest, Spacewar, Speed Freak, Star Castle, Star Hawk,
300  * Tail Gunner, War of the Worlds, Warrior
301  *
302  * For reference, all of the cinematronics games are:
303  * Armor Attack, Barrier, Boxing Bugs, Demon, Ripoff, Solar Quest,
304  * Spacewar, Speed Freak, Star Castle, Star Hawk, Sundance, Tail Gunner
305  * War of the worlds, Warrior
306  * (There is another, but it has not been made available yet)
307  *
308  * USAGE:
309  * 1) The emulator works like any other "processor" emulator
310  * 2) It does expect a few variables to be set, however, indicating
311  *    which switches were connected on the original boards. (Most
312  *    important is the variable to chose whethor or not to use the MI
313  *    or EI flag...). See below.
314  * 3) The emulator expects the memory to ALREADY be interleaved into
315  *    "normalacy". The cinem ROMs are slow to read otherwise...
316  * 4) Endianness doesn't matter; its code nice and slowly :)
317  * 5) Compile time options may be set to obtain debugging tool, runtime
318  *    traces, etc etc.
319  * 6) The emulator does the vector handling; you need provide a routine
320  *    to receive the vector draw requests, so that it may queue them up
321  * 7) Zonn will be documenting the method by which the game palettes
322  *    may be derived, where applicable.
323  *
324  * INITIALIZATION:
325  * Take, for example, the game RipOff (the reaosn I got into this mess :).
326  * The following variables need to be set, and the functions called, in
327  * order to have the "cpu" run properly (courtesy Neil Bradley, Zonn Moore):
328  * bFlipX = 0;  bFlipY = 1;     bSwapXY = 0;     (for vector generation)
329  * ioInputs = 0xffff; ioSwitches = 0xfff0;  (cleared values)
330  * bOverlay = 0xff;                                 (No overlay)
331  * cineSetJMI(1);                                      (JMI Allowed)
332  * cineSetMSize(0);                            (8K)
333  * cineSetMonitor(0);                       (Bi-level display)
334  *
335  * If masking values are needed by anyone for the various game
336  * controllers and whatnot, let me know, and I'll put up a document.
337  *
338  * SUPPORT:
339  * FTP and WEB:
340  *   Official support archive is at ftp.retrocade.com and www.retrocade.com.
341  *   Various mirrors will be kept (ie: skeleton.org, the Emulation Repository,
342  *   erc.), and are yet to be announced.
343  * EMAIL:
344  *   The C version: Jeff Mitchell is skeezix@skeleton.org
345  *   The ASM version: Neil Bradley (neil@synthcom.com) and
346  *                    Zonn Moore (zonn@zonn.com)
347  *
348  * An emulator for the Cinematronics vector game hardware, originally
349  * for use in the Retrocade emulator project. All work is based on
350  * documentation and sources and testbeds created by Zonn. He's a freak.
351  *
352  * Last modified: 02/17/98
353  *
354  * 12/04/97:      Created a "SETFC" macro for storing the flag_C var
355  *                (shift and mask it at inspection time)
356  * 12/??/97:      Fixed subtraction bugs (using register_B for A0 instead
357  *                of register_A). Fixed input mask value in opINP.
358  * 12/24/97:      Added #define for CCPUSSTEP for single stepping
359  * 12/25/97:      Added ioSwitches &= (!SW_ABORT) into the top
360  *                of the cineExec call. This fixed Star Castle, but
361  *                broke others :/
362  *                  Made opLSLe_A_.. handle multiple consecutive occurances
363  *                so things would be a little faster, and so DOS versus
364  *                Unix traces would be easier.
365  *                  Changed above ioSwitches fix to ~SW_ABORT instead. This
366  *                rebroke StarCastle and Sundance, but fixed Barrier. *sigh*
367  */
368 
369 /* Optional #defines for debugging:
370  * CCPUBREAK -- causes stopage on unknown upcodes
371  * For these to operate, the debugging variables must be set as well.
372  * This allows runtime selection of traces, etc.
373  * CCPUSSTEP -- force single stepping
374  *
375  * Debug Variables:
376  * ccpubreak -- set to non-zero to enable "break"ing
377  */
378 
379 /* 1) Need to macro-ize everything, so that I can have this whole
380  *    source file written by a perl script generator easier.
381  * 4) Any of the jumps weird? JNC?
382  * 5) JEI's all fucked? Are the tredirector's set right in the first place?
383  *    What about all those damned JPP8, 16 and 32s? They work right?
384  * 6) Store ccpu_jmi_dip and other new state vars in struct?
385  * 7) Various OUT functions correct?
386  */
387 
388 #include <stdio.h>
389 #include <string.h>
390 
391 #include "ccpu.h"
392 
393 /*
394  * Use 0xF000 so as to keep the current page, since it may well
395  * have been changed with JPP.
396  */
397 #define JMP() register_PC = ((register_PC - 1) & 0xF000) + register_J; ccpu_ICount -= 2
398 
399 /* Declare needed macros */
400 #ifdef macintosh
401 #define UNFINISHED(x)  { SysBeep (0); }
402 #else
403 #define UNFINISHED(x)  { /*logerror("UNFINISHED: %s\n", x);*/ }
404 #endif
405 
406 /* Handy new operators ... */
407 
408 /* for Zonn translation :) */
409 #define SAR(var,arg)    (((signed short int) var) >> arg)
410 
411 /* for setting/checking the A0 flag */
412 #define SETA0(var)    (acc_a0 = var)
413 #define GETA0()       (acc_a0)
414 
415 /* for setting/checking the Carry flag */
416 #define SETFC(val)    (flag_C = val)
417 #define GETFC()       ((flag_C >> 8) & 0xFF)
418 
419 static int bailOut = FALSE;
420 
421 /* C-CPU context information begins --  */
422 static CINEWORD register_PC = 0; /* C-CPU registers; program counter */
423 static CINEWORD register_A = 0;  /* A-Register (accumulator) */
424 static CINEWORD register_B = 0;  /* B-Register (accumulator) */
425 static CINEBYTE register_I = 0;  /* I-Register (last access RAM location) */
426 static CINEWORD register_J = 0;  /* J-Register (target address for JMP opcodes) */
427 static CINEBYTE register_P = 0;  /* Page-Register (4 bits) */
428 static CINEWORD FromX = 0;       /* X-Register (start of a vector) */
429 static CINEWORD FromY = 0;       /* Y-Register (start of a vector) */
430 static CINEWORD register_T = 0;  /* T-Register (vector draw length timer) */
431 static CINEWORD flag_C = 0;      /* C-CPU flags; carry. Is word sized, instead
432                                   * of CINEBYTE, so we can do direct assignment
433                                   * and then change to BYTE during inspection.
434                                   */
435 
436 static CINEWORD cmp_old = 0;     /* last accumulator value */
437 static CINEWORD cmp_new = 0;     /* new accumulator value */
438 static CINEBYTE acc_a0 = 0;      /* bit0 of A-reg at last accumulator access */
439 
440 static CINESTATE state = state_A;/* C-CPU state machine current state */
441 
442 static CINEWORD  ram[256];       /* C-CPU ram (for all pages) */
443 
444 static int ccpu_jmi_dip = 0;     /* as set by cineSetJMI */
445 static int ccpu_msize = 0;       /* as set by cineSetMSize */
446 static int ccpu_monitor = 0;     /* as set by cineSetMonitor */
447 
448 static CINEBYTE vgShiftLength = 0; /* number of shifts loaded into length reg */
449 static CINEWORD vgColour = 0;
450 /* -- Context information ends. */
451 
452 
453 int bNewFrame;
454 
455 /* Note: I have removed all of this assuming that the vector drawing function can handle things */
456 #if !RAW_VECTORS
457 int bFlipX;
458 int bFlipY;
459 int bSwapXY;
460 int bOverlay;
461 
462 extern int sdwGameXSize;
463 extern int sdwGameYSize;
464 extern int sdwXOffset;
465 extern int sdwYOffset;
466 #endif
467 
468 
469 
470 /* functions */
471 
472 #include "ccputabl.c"
473 
474 /*
475  * cineExec() is what performs all the "processors" work; it will
476  * continue to execute until something horrible happens, a watchpoint
477  * is hit, cycle count exceeded, or other happy things.
478  */
479 
cineExec(CINELONG cycles)480 CINELONG cineExec (CINELONG cycles)
481 {
482 	ccpu_ICount = cycles;
483 	bailOut = FALSE;
484 
485    	do
486    	{
487    		int opcode;
488 
489 		/*
490 		 * goto the correct piece of code
491 		 * for the current opcode. That piece of code will set the state
492 		 * for the next run, as well.
493 		 */
494 
495 		opcode = CCPU_FETCH (register_PC++);
496 		state = (*cineops[state][opcode]) (opcode);
497         ccpu_ICount -= ccpu_cycles[opcode];
498 
499 
500 		/*
501 		 * the opcode code has set a state and done mischief with flags and
502 		 * the program counter; now jump back to the top and run through another
503 		 * opcode.
504 		 */
505 		if (bailOut)
506 /*			ccpu_ICount = 0; */
507 			ccpu_ICount -= 100;
508 	}
509 	while (ccpu_ICount > 0);
510 
511 	return cycles - ccpu_ICount;
512 }
513 
514 
515 /*
516  * the actual opcode code; each piece should be careful to
517  * (1) set the correct state
518  * (2) increment the program counter as necessary
519  * (3) piss with the flags as needed
520  * otherwise the next opcode will be completely buggered.
521  */
522 
opINP_A_AA(int opcode)523 CINESTATE opINP_A_AA (int opcode)
524 {
525 	/*
526 	 * bottom 4 bits of opcode are the position of the bit we want;
527 	 * obtain input value, shift over that no, and truncate to last bit.
528 	 * NOTE: Masking 0x07 does interesting things on Sundance and
529 	 * others, but masking 0x0F makes RipOff and others actually work :)
530 	 */
531 
532 	cmp_new = (CCPU_READPORT (CCPU_PORT_IOINPUTS) >> (opcode & 0x0F)) & 0x01;
533 
534 	SETA0 (register_A);               /* save old accA bit0 */
535 	SETFC (register_A);
536 
537 	cmp_old = register_A;               /* save old accB */
538 	register_A = cmp_new;               /* load new accB; zero other bits */
539 
540 	return state_AA;
541 }
542 
opINP_B_AA(int opcode)543 CINESTATE opINP_B_AA (int opcode)
544 {
545 	/*
546 	 * bottom 3 bits of opcode are the position of the bit we want;
547 	 * obtain Switches value, shift over that no, and truncate to last bit.
548 	 */
549 
550 	cmp_new = (CCPU_READPORT (CCPU_PORT_IOSWITCHES) >> (opcode & 0x07)) & 0x01;
551 
552 	SETA0 (register_A);               /* save old accA bit0 */
553 	SETFC (register_A);
554 
555 	cmp_old = register_B;               /* save old accB */
556 	register_B = cmp_new;               /* load new accB; zero other bits */
557 
558 	return state_AA;
559 }
560 
opOUTsnd_A(int opcode)561 CINESTATE opOUTsnd_A (int opcode)
562 {
563 	if (!(register_A & 0x01))
564 		CCPU_WRITEPORT (CCPU_PORT_IOOUTPUTS, CCPU_READPORT (CCPU_PORT_IOOUTPUTS) | (0x01 << (opcode & 0x07)));
565 	else
566 		CCPU_WRITEPORT (CCPU_PORT_IOOUTPUTS, CCPU_READPORT (CCPU_PORT_IOOUTPUTS) & ~(0x01 << (opcode & 0x07)));
567 
568 	if ((opcode & 0x07) == 0x05)
569 	{
570 		/* reset coin counter */
571 	}
572 
573 	return state_A;
574 }
575 
opOUTbi_A_A(int opcode)576 CINESTATE opOUTbi_A_A (int opcode)
577 {
578 	if ((opcode & 0x07) != 6)
579 		return opOUTsnd_A (opcode);
580 
581 	vgColour = register_A & 0x01 ? 0x0f: 0x07;
582 
583 	return state_A;
584 }
585 
opOUT16_A_A(int opcode)586 CINESTATE opOUT16_A_A (int opcode)
587 {
588 	if ((opcode & 0x07) != 6)
589 		return opOUTsnd_A (opcode);
590 
591 	if ((register_A & 0x1) != 1)
592 	{
593 		vgColour = FromX & 0x0F;
594 
595 		if (!vgColour)
596 			vgColour = 1;
597 	}
598 
599 	return state_A;
600 }
601 
opOUT64_A_A(int opcode)602 CINESTATE opOUT64_A_A (int opcode)
603 {
604 	return state_A;
605 }
606 
opOUTWW_A_A(int opcode)607 CINESTATE opOUTWW_A_A (int opcode)
608 {
609 	if ((opcode & 0x07) != 6)
610 		return opOUTsnd_A (opcode);
611 
612 	if ((register_A & 0x1) == 1)
613 	{
614 		CINEWORD temp_word = ~FromX & 0x0FFF;
615 		if (!temp_word)   /* black */
616 			vgColour = 0;
617 		else
618 		{   /* non-black */
619 			if (temp_word & 0x0888)
620 				/* bright */
621 				vgColour = ((temp_word >> 1) & 0x04) | ((temp_word >> 6) & 0x02) | ((temp_word >> 11) & 0x01) | 0x08;
622 			else if (temp_word & 0x0444)
623 				/* dim bits */
624 				vgColour = (temp_word & 0x04) | ((temp_word >> 5) & 0x02) | ((temp_word >> 10) & 0x01);
625 		}
626 	} /* colour change? == 1 */
627 
628 	return state_A;
629 }
630 
opOUTsnd_B(int opcode)631 CINESTATE opOUTsnd_B (int opcode)
632 {
633 	return state_BB;
634 }
635 
opOUTbi_B_BB(int opcode)636 CINESTATE opOUTbi_B_BB (int opcode)
637 {
638 	CINEBYTE temp_byte = opcode & 0x07;
639 
640 	if (temp_byte - 0x06)
641 		return opOUTsnd_B (opcode);
642 
643 	vgColour = ((register_B & 0x01) << 3) | 0x07;
644 
645 	return state_BB;
646 }
647 
opOUT16_B_BB(int opcode)648 CINESTATE opOUT16_B_BB (int opcode)
649 {
650 	CINEBYTE temp_byte = opcode & 0x07;
651 
652 	if (temp_byte - 0x06)
653 		return opOUTsnd_B (opcode);
654 
655 	if ((register_B & 0xFF) != 1)
656 	{
657 		vgColour = FromX & 0x0F;
658 
659 		if (!vgColour)
660 			vgColour = 1;
661 	}
662 
663 	return state_BB;
664 }
665 
opOUT64_B_BB(int opcode)666 CINESTATE opOUT64_B_BB (int opcode)
667 {
668 	return state_BB;
669 }
670 
opOUTWW_B_BB(int opcode)671 CINESTATE opOUTWW_B_BB (int opcode)
672 {
673 	return state_BB;
674 }
675 
676   /* LDA imm (0x) */
opLDAimm_A_AA(int opcode)677 CINESTATE opLDAimm_A_AA (int opcode)
678 {
679 	CINEWORD temp_word = opcode & 0x0F;   /* pick up immediate value */
680 	temp_word <<= 8;                          /* LDAimm is the HIGH nibble!*/
681 
682 	cmp_new = temp_word;                      /* set new comparison flag */
683 
684 	SETA0 (register_A);                     /* save old accA bit0 */
685 	SETFC (register_A);                     /* ??? clear carry? */
686 
687 	cmp_old = register_A;                     /* step back cmp flag */
688 	register_A = temp_word;                   /* set the register */
689 
690 	return state_AA;                           /* swap state and end opcode */
691 }
692 
opLDAimm_B_AA(int opcode)693 CINESTATE opLDAimm_B_AA (int opcode)
694 {
695 	CINEWORD temp_word = opcode & 0x0F;   /* pick up immediate value */
696 	temp_word <<= 8;                          /* LDAimm is the HIGH nibble!*/
697 
698 	cmp_new = temp_word;                      /* set new comparison flag */
699 
700 	SETA0 (register_A);                     /* save old accA bit0 */
701 	SETFC (register_A);
702 
703 	cmp_old = register_B;                     /* step back cmp flag */
704 	register_B = temp_word;                   /* set the register */
705 
706 	return state_AA;
707 }
708 
opLDAdir_A_AA(int opcode)709 CINESTATE opLDAdir_A_AA (int opcode)
710 {
711 	CINEBYTE temp_byte = opcode & 0x0F;        /* snag imm value */
712 
713 	register_I = (register_P << 4) + temp_byte;  /* set I register */
714 
715 	cmp_new = ram[register_I];                  /* new acc value */
716 
717 	SETA0 (register_A);                          /* back up bit0 */
718 	SETFC (register_A);
719 
720 	cmp_old = register_A;                          /* store old acc */
721 	register_A = cmp_new;                          /* store new acc */
722 
723 	return state_AA;
724 }
725 
opLDAdir_B_AA(int opcode)726 CINESTATE opLDAdir_B_AA (int opcode)
727 {
728 	CINEBYTE temp_byte = opcode & 0x0F;        /* snag imm value */
729 
730 	register_I = (register_P << 4) + temp_byte;  /* set I register */
731 
732 	cmp_new = ram[register_I];                  /* new acc value */
733 
734 	SETA0 (register_A);                          /* back up bit0 */
735 	SETFC (register_A);
736 
737 	cmp_old = register_B;                          /* store old acc */
738 	register_B = cmp_new;                          /* store new acc */
739 
740 	return state_AA;
741 }
742 
opLDAirg_A_AA(int opcode)743 CINESTATE opLDAirg_A_AA (int opcode)
744 {
745 	cmp_new = ram[register_I];
746 
747 	SETA0 (register_A);
748 	SETFC (register_A);
749 
750 	cmp_old = register_A;
751 	register_A = cmp_new;
752 
753 	return state_AA;
754 }
755 
opLDAirg_B_AA(int opcode)756 CINESTATE opLDAirg_B_AA (int opcode)
757 {
758 	cmp_new = ram[register_I];
759 
760 	SETA0 (register_A);
761 	SETFC (register_A);
762 
763 	cmp_old = register_B;
764 	register_B = cmp_new;
765 
766 	return state_AA;
767 }
768 
769   /* ADD imm */
opADDimm_A_AA(int opcode)770 CINESTATE opADDimm_A_AA (int opcode)
771 {
772 	CINEWORD temp_word = opcode & 0x0F;     /* get imm value */
773 
774 	cmp_new = temp_word;                        /* new acc value */
775 	SETA0 (register_A);                       /* save old accA bit0 */
776 	cmp_old = register_A;                       /* store old acc for later */
777 
778 	register_A += temp_word;                    /* add values */
779 	SETFC (register_A);                       /* store carry and extra */
780 	register_A &= 0xFFF;                        /* toss out >12bit carry */
781 
782 	return state_AA;
783 }
784 
opADDimm_B_AA(int opcode)785 CINESTATE opADDimm_B_AA (int opcode)
786 {
787 	CINEWORD temp_word = opcode & 0x0F;     /* get imm value */
788 
789 	cmp_new = temp_word;                        /* new acc value */
790 	SETA0 (register_A);                       /* save old accA bit0 */
791 	cmp_old = register_B;                       /* store old acc for later */
792 
793 	register_B += temp_word;                    /* add values */
794 	SETFC (register_B);                       /* store carry and extra */
795 	register_B &= 0xFFF;                        /* toss out >12bit carry */
796 
797 	return state_AA;
798 }
799 
800   /* ADD imm extended */
opADDimmX_A_AA(int opcode)801 CINESTATE opADDimmX_A_AA (int opcode)
802 {
803 	cmp_new = CCPU_FETCH (register_PC++);       /* get extended value */
804 	SETA0 (register_A);                       /* save old accA bit0 */
805 	cmp_old = register_A;                       /* store old acc for later */
806 
807 	register_A += cmp_new;                      /* add values */
808 	SETFC (register_A);                       /* store carry and extra */
809 	register_A &= 0xFFF;                        /* toss out >12bit carry */
810 
811 	return state_AA;
812 }
813 
opADDimmX_B_AA(int opcode)814 CINESTATE opADDimmX_B_AA (int opcode)
815 {
816 	cmp_new = CCPU_FETCH (register_PC++);       /* get extended value */
817 	SETA0 (register_A);                       /* save old accA bit0 */
818 	cmp_old = register_B;                       /* store old acc for later */
819 
820 	register_B += cmp_new;                      /* add values */
821 	SETFC (register_B);                       /* store carry and extra */
822 	register_B &= 0xFFF;                        /* toss out >12bit carry */
823 
824 	return state_AA;
825 }
826 
opADDdir_A_AA(int opcode)827 CINESTATE opADDdir_A_AA (int opcode)
828 {
829 	CINEBYTE temp_byte = opcode & 0x0F;         /* fetch imm value */
830 
831 	register_I = (register_P << 4) + temp_byte;   /* set regI addr */
832 
833 	cmp_new = ram[register_I];                   /* fetch imm real value */
834 	SETA0 (register_A);                           /* store bit0 */
835 	cmp_old = register_A;                           /* store old acc value */
836 
837 	register_A += cmp_new;                          /* do acc operation */
838 	SETFC (register_A);                           /* store carry and extra */
839 	register_A &= 0x0FFF;
840 
841 	return state_AA;
842 }
843 
opADDdir_B_AA(int opcode)844 CINESTATE opADDdir_B_AA (int opcode)
845 {
846 	CINEBYTE temp_byte = opcode & 0x0F;         /* fetch imm value */
847 
848 	register_I = (register_P << 4) + temp_byte;   /* set regI addr */
849 
850 	cmp_new = ram[register_I];                   /* fetch imm real value */
851 	SETA0 (register_A);                           /* store bit0 */
852 	cmp_old = register_B;                           /* store old acc value */
853 
854 	register_B += cmp_new;                          /* do acc operation */
855 	SETFC (register_B);                           /* store carry and extra */
856 	register_B &= 0x0FFF;
857 
858 	return state_AA;
859 }
860 
opAWDirg_A_AA(int opcode)861 CINESTATE opAWDirg_A_AA (int opcode)
862 {
863 	cmp_new = ram[register_I];
864 	SETA0 (register_A);
865 	cmp_old = register_A;
866 
867 	register_A += cmp_new;
868 	SETFC (register_A);
869 	register_A &= 0x0FFF;
870 
871 	return state_AA;
872 }
873 
opAWDirg_B_AA(int opcode)874 CINESTATE opAWDirg_B_AA (int opcode)
875 {
876 	cmp_new = ram[register_I];
877 	SETA0 (register_A);
878 	cmp_old = register_B;
879 
880 	register_B += cmp_new;
881 	SETFC (register_B);
882 	register_B &= 0x0FFF;
883 
884 	return state_AA;
885 }
886 
opSUBimm_A_AA(int opcode)887 CINESTATE opSUBimm_A_AA (int opcode)
888 {
889 	/*
890 	 * 	SUBtractions are negate-and-add instructions of the CCPU; what
891 	 * 	a pain in the ass.
892 	 */
893 
894 	CINEWORD temp_word = opcode & 0x0F;
895 
896 	cmp_new = temp_word;
897 	SETA0 (register_A);
898 	cmp_old = register_A;
899 
900 	temp_word = (temp_word ^ 0xFFF) + 1;         /* ones compliment */
901 	register_A += temp_word;                       /* add */
902 	SETFC (register_A);                          /* pick up top bits */
903 	register_A &= 0x0FFF;                          /* mask final regA value */
904 
905 	return state_AA;
906 }
907 
opSUBimm_B_AA(int opcode)908 CINESTATE opSUBimm_B_AA (int opcode)
909 {
910 	/*
911 	 * SUBtractions are negate-and-add instructions of the CCPU; what
912 	 * a pain in the ass.
913 	 */
914 
915 	CINEWORD temp_word = opcode & 0x0F;
916 
917 	cmp_new = temp_word;
918 	SETA0 (register_A);
919 	cmp_old = register_B;
920 
921 	temp_word = (temp_word ^ 0xFFF) + 1;         /* ones compliment */
922 	register_B += temp_word;                       /* add */
923 	SETFC (register_B);                          /* pick up top bits */
924 	register_B &= 0x0FFF;                          /* mask final regA value */
925 
926 	return state_AA;
927 }
928 
opSUBimmX_A_AA(int opcode)929 CINESTATE opSUBimmX_A_AA (int opcode)
930 {
931 	CINEWORD temp_word = CCPU_FETCH (register_PC++);       /* snag imm value */
932 
933 	cmp_new = temp_word;                          /* save cmp value */
934 	SETA0 (register_A);                         /* store bit0 */
935 	cmp_old = register_A;                         /* back up regA */
936 
937 	temp_word = (temp_word ^ 0xFFF) + 1;        /* ones compliment */
938 	register_A += temp_word;                      /* add */
939 	SETFC (register_A);                         /* pick up top bits */
940 	register_A &= 0x0FFF;                         /* mask final regA value */
941 
942 	return state_AA;
943 }
944 
opSUBimmX_B_AA(int opcode)945 CINESTATE opSUBimmX_B_AA (int opcode)
946 {
947 	CINEWORD temp_word = CCPU_FETCH (register_PC++);       /* snag imm value */
948 
949 	cmp_new = temp_word;                          /* save cmp value */
950 	SETA0 (register_A);                         /* store bit0 */
951 	cmp_old = register_B;                         /* back up regA */
952 
953 	temp_word = (temp_word ^ 0xFFF) + 1;        /* ones compliment */
954 	register_B += temp_word;                      /* add */
955 	SETFC (register_B);                         /* pick up top bits */
956 	register_B &= 0x0FFF;                         /* mask final regA value */
957 
958 	return state_AA;
959 }
960 
opSUBdir_A_AA(int opcode)961 CINESTATE opSUBdir_A_AA (int opcode)
962 {
963 	CINEWORD temp_word = opcode & 0x0F;         /* fetch imm value */
964 
965 	register_I = (register_P << 4) + temp_word;   /* set regI addr */
966 
967 	cmp_new = ram[register_I];
968 	SETA0 (register_A);
969 	cmp_old = register_A;
970 
971 	temp_word = (cmp_new ^ 0xFFF) + 1;           /* ones compliment */
972 	register_A += temp_word;                       /* add */
973 	SETFC (register_A);                          /* pick up top bits */
974 	register_A &= 0x0FFF;                          /* mask final regA value */
975 
976 	return state_AA;
977 }
978 
opSUBdir_B_AA(int opcode)979 CINESTATE opSUBdir_B_AA (int opcode)
980 {
981 	CINEWORD temp_word;
982 	CINEBYTE temp_byte = opcode & 0x0F;         /* fetch imm value */
983 
984 	register_I = (register_P << 4) + temp_byte;   /* set regI addr */
985 
986 	cmp_new = ram[register_I];
987 	SETA0 (register_A);
988 	cmp_old = register_B;
989 
990 	temp_word = (cmp_new ^ 0xFFF) + 1;           /* ones compliment */
991 	register_B += temp_word;                       /* add */
992 	SETFC (register_B);                          /* pick up top bits */
993 	register_B &= 0x0FFF;                          /* mask final regA value */
994 
995 	return state_AA;
996 }
997 
opSUBirg_A_AA(int opcode)998 CINESTATE opSUBirg_A_AA (int opcode)
999 {
1000 	CINEWORD temp_word;
1001 
1002 	/* sub [i] */
1003 	cmp_new = ram[register_I];
1004 	SETA0 (register_A);
1005 	cmp_old = register_A;
1006 
1007 	temp_word = (cmp_new ^ 0xFFF) + 1;           /* ones compliment */
1008 	register_A += temp_word;                       /* add */
1009 	SETFC (register_A);                          /* pick up top bits */
1010 	register_A &= 0x0FFF;                          /* mask final regA value */
1011 
1012 	return state_AA;
1013 }
1014 
opSUBirg_B_AA(int opcode)1015 CINESTATE opSUBirg_B_AA (int opcode)
1016 {
1017 	CINEWORD temp_word;
1018 
1019 	/* sub [i] */
1020 	cmp_new = ram[register_I];
1021 	SETA0 (register_A);
1022 	cmp_old = register_B;
1023 
1024 	temp_word = (cmp_new ^ 0xFFF) + 1;           /* ones compliment */
1025 	register_B += temp_word;                       /* add */
1026 	SETFC (register_B);                          /* pick up top bits */
1027 	register_B &= 0x0FFF;                          /* mask final regA value */
1028 
1029 	return state_AA;
1030 }
1031 
1032   /* CMP dir */
opCMPdir_A_AA(int opcode)1033 CINESTATE opCMPdir_A_AA (int opcode)
1034 {
1035 	/*
1036 	 * compare direct mode; don't modify regs, just set carry flag or not.
1037 	 */
1038 
1039 	CINEWORD temp_word;
1040 	CINEBYTE temp_byte = opcode & 0x0F;       /* obtain relative addr */
1041 
1042 	register_I = (register_P << 4) + temp_byte; /* build real addr */
1043 
1044 	temp_word = ram[register_I];
1045 	cmp_new = temp_word;                          /* new acc value */
1046 	SETA0 (register_A);                         /* backup bit0 */
1047 	cmp_old = register_A;                         /* backup old acc */
1048 
1049 	temp_word = (temp_word ^ 0xFFF) + 1;        /* ones compliment */
1050 	temp_word += register_A;
1051 	SETFC (temp_word);                          /* pick up top bits */
1052 
1053 	return state_AA;
1054 }
1055 
opCMPdir_B_AA(int opcode)1056 CINESTATE opCMPdir_B_AA (int opcode)
1057 {
1058 	CINEWORD temp_word;
1059 	CINEBYTE temp_byte = opcode & 0x0F;       /* obtain relative addr */
1060 
1061 	register_I = (register_P << 4) + temp_byte; /* build real addr */
1062 
1063 	temp_word = ram[register_I];
1064 	cmp_new = temp_word;                          /* new acc value */
1065 	SETA0 (register_A);                         /* backup bit0 */
1066 	cmp_old = register_B;                         /* backup old acc */
1067 
1068 	temp_word = (temp_word ^ 0xFFF) + 1;        /* ones compliment */
1069 	temp_word += register_B;
1070 	SETFC (temp_word);                          /* pick up top bits */
1071 
1072 	return state_AA;
1073 }
1074 
1075   /* AND [i] */
opANDirg_A_AA(int opcode)1076 CINESTATE opANDirg_A_AA (int opcode)
1077 {
1078 	cmp_new = ram[register_I];                /* new acc value */
1079 	SETA0 (register_A);
1080 	SETFC (register_A);
1081 	cmp_old = register_A;
1082 
1083 	register_A &= cmp_new;
1084 
1085 	return state_AA;
1086 }
1087 
opANDirg_B_AA(int opcode)1088 CINESTATE opANDirg_B_AA (int opcode)
1089 {
1090 	cmp_new = ram[register_I];                /* new acc value */
1091 	SETA0 (register_A);
1092 	SETFC (register_A);
1093 	cmp_old = register_B;
1094 
1095 	register_B &= cmp_new;
1096 
1097 	return state_AA;
1098 }
1099 
1100   /* LDJ imm */
opLDJimm_A_A(int opcode)1101 CINESTATE opLDJimm_A_A (int opcode)
1102 {
1103 	CINEBYTE temp_byte = CCPU_FETCH (register_PC++);      /* upper part of address */
1104 	temp_byte = (temp_byte << 4) |             /* Silly CCPU; Swap */
1105 	            (temp_byte >> 4);              /* nibbles */
1106 
1107 	/* put the upper 8 bits above the existing 4 bits */
1108 	register_J = (opcode & 0x0F) | (temp_byte << 4);
1109 
1110 	return state_A;
1111 }
1112 
opLDJimm_B_BB(int opcode)1113 CINESTATE opLDJimm_B_BB (int opcode)
1114 {
1115 	CINEBYTE temp_byte = CCPU_FETCH (register_PC++);      /* upper part of address */
1116 	temp_byte = (temp_byte << 4) |             /* Silly CCPU; Swap */
1117 	            (temp_byte >> 4);              /* nibbles */
1118 
1119 	/* put the upper 8 bits above the existing 4 bits */
1120 	register_J = (opcode & 0x0F) | (temp_byte << 4);
1121 
1122 	return state_BB;
1123 }
1124 
1125   /* LDJ irg */
opLDJirg_A_A(int opcode)1126 CINESTATE opLDJirg_A_A (int opcode)
1127 {
1128 	/* load J reg from value at last dir addr */
1129 	register_J = ram[register_I];
1130 	return state_A;
1131 }
1132 
opLDJirg_B_BB(int opcode)1133 CINESTATE opLDJirg_B_BB (int opcode)
1134 {
1135 	register_J = ram[register_I];
1136 	return state_BB;
1137 }
1138 
1139   /* LDP imm */
opLDPimm_A_A(int opcode)1140 CINESTATE opLDPimm_A_A (int opcode)
1141 {
1142 	/* load page register from immediate */
1143 	register_P = opcode & 0x0F;  /* set page register */
1144 	return state_A;
1145 }
1146 
opLDPimm_B_BB(int opcode)1147 CINESTATE opLDPimm_B_BB (int opcode)
1148 {
1149 	/* load page register from immediate */
1150 	register_P = opcode & 0x0F;  /* set page register */
1151 	return state_BB;
1152 }
1153 
1154   /* LDI dir */
opLDIdir_A_A(int opcode)1155 CINESTATE opLDIdir_A_A (int opcode)
1156 {
1157 	/* load regI directly .. */
1158 
1159 	CINEBYTE temp_byte = (register_P << 4) +           /* get ram page ... */
1160 	         (opcode & 0x0F); /* and imm half of ram addr.. */
1161 
1162 	register_I = ram[temp_byte] & 0xFF;      /* set/mask new register_I */
1163 
1164 	return state_A;
1165 }
1166 
opLDIdir_B_BB(int opcode)1167 CINESTATE opLDIdir_B_BB (int opcode)
1168 {
1169 	CINEBYTE temp_byte = (register_P << 4) +           /* get ram page ... */
1170 	         (opcode & 0x0F); /* and imm half of ram addr.. */
1171 
1172 	register_I = ram[temp_byte] & 0xFF;      /* set/mask new register_I */
1173 
1174 	return state_BB;
1175 }
1176 
1177   /* STA dir */
opSTAdir_A_A(int opcode)1178 CINESTATE opSTAdir_A_A (int opcode)
1179 {
1180 	CINEBYTE temp_byte = opcode & 0x0F;        /* snag imm value */
1181 
1182 	register_I = (register_P << 4) + temp_byte;  /* set I register */
1183 
1184 	ram[register_I] = register_A;               /* store acc to RAM */
1185 
1186 	return state_A;
1187 }
1188 
opSTAdir_B_BB(int opcode)1189 CINESTATE opSTAdir_B_BB (int opcode)
1190 {
1191 	CINEBYTE temp_byte = opcode & 0x0F;        /* snag imm value */
1192 
1193 	register_I = (register_P << 4) + temp_byte;  /* set I register */
1194 
1195 	ram[register_I] = register_B;               /* store acc to RAM */
1196 
1197 	return state_BB;
1198 }
1199 
1200   /* STA irg */
opSTAirg_A_A(int opcode)1201 CINESTATE opSTAirg_A_A (int opcode)
1202 {
1203 	/*
1204 	 * STA into address specified in regI. Nice and easy :)
1205 	 */
1206 
1207 	ram[register_I] = register_A;               /* store acc */
1208 
1209 	return state_A;
1210 }
1211 
opSTAirg_B_BB(int opcode)1212 CINESTATE opSTAirg_B_BB (int opcode)
1213 {
1214 	ram[register_I] = register_B;               /* store acc */
1215 
1216 	return state_BB;
1217 }
1218 
1219   /* XLT */
opXLT_A_AA(int opcode)1220 CINESTATE opXLT_A_AA (int opcode)
1221 {
1222 	/*
1223 	 * XLT is weird; it loads the current accumulator with the bytevalue
1224 	 * at ROM location pointed to by the accumulator; this allows the
1225 	 * program to read the program itself..
1226 	 * 		NOTE! Next opcode is *IGNORED!* because of a twisted side-effect
1227 	 */
1228 
1229 	cmp_new = CCPU_FETCH (((register_PC - 1) & 0xF000) + register_A);   /* store new acc value */
1230 	SETA0 (register_A);           /* store bit0 */
1231 	SETFC (register_A);
1232 	cmp_old = register_A;           /* back up acc */
1233 
1234 	register_A = cmp_new;           /* new acc value */
1235 
1236 	register_PC++;               /* bump PC twice because XLT is fucked up */
1237 	return state_AA;
1238 }
1239 
opXLT_B_AA(int opcode)1240 CINESTATE opXLT_B_AA (int opcode)
1241 {
1242 	cmp_new = CCPU_FETCH (((register_PC - 1) & 0xF000) + register_B);   /* store new acc value */
1243 	SETA0 (register_A);           /* store bit0 */
1244 	SETFC (register_A);
1245 	cmp_old = register_B;           /* back up acc */
1246 
1247 	register_B = cmp_new;           /* new acc value */
1248 
1249 	register_PC++;               /* bump PC twice because XLT is fucked up */
1250 	return state_AA;
1251 }
1252 
1253   /* MUL [i] */
opMULirg_A_AA(int opcode)1254 CINESTATE opMULirg_A_AA (int opcode)
1255 {
1256 	CINEBYTE temp_byte = opcode & 0xFF;    /* (for ease and speed) */
1257 	CINEWORD temp_word = ram[register_I];               /* pick up ram value */
1258 
1259 	cmp_new = temp_word;
1260 
1261 	temp_word <<= 4;                              /* shift into ADD position */
1262 	register_B <<= 4;                             /* get sign bit 15 */
1263 	register_B |= (register_A >> 8);            /* bring in A high nibble */
1264 
1265 	register_A = ((register_A & 0xFF) << 8) | /* shift over 8 bits */
1266 	          temp_byte;  /* pick up opcode */
1267 
1268 	if (register_A & 0x100)
1269 	{        				   /* 1bit shifted out? */
1270 		register_A = (register_A >> 8) |
1271 		             ((register_B & 0xFF) << 8);
1272 
1273 		SETA0 (register_A & 0xFF);                  /* store bit0 */
1274 
1275 		register_A >>= 1;
1276 		register_A &= 0xFFF;
1277 
1278 		register_B = SAR(register_B,4);
1279 		cmp_old = register_B & 0x0F;
1280 
1281 		register_B = SAR(register_B,1);
1282 
1283 		register_B &= 0xFFF;
1284 		register_B += cmp_new;
1285 
1286 		SETFC (register_B);
1287 
1288 		register_B &= 0xFFF;
1289 	}
1290 	else
1291 	{
1292 		register_A = (register_A >> 8) |    /* Bhigh | Alow */
1293 		             ((register_B & 0xFF) << 8);
1294 
1295 		temp_word = register_A & 0xFFF;
1296 
1297 		SETA0 (temp_word & 0xFF);                   /* store bit0 */
1298 		cmp_old = temp_word;
1299 
1300 		temp_word += cmp_new;
1301 		SETFC (temp_word);
1302 
1303 		register_A >>= 1;
1304 		register_A &= 0xFFF;
1305 
1306 		register_B = SAR(register_B,5);
1307 		register_B &= 0xFFF;
1308 	}
1309 
1310 	return state_AA;
1311 }
1312 
opMULirg_B_AA(int opcode)1313 CINESTATE opMULirg_B_AA (int opcode)
1314 {
1315 	CINEWORD temp_word = ram[register_I];
1316 
1317 	cmp_new = temp_word;
1318 	cmp_old = register_B;
1319 	SETA0 (register_A & 0xFF);
1320 
1321 	register_B <<= 4;
1322 
1323 	register_B = SAR(register_B,5);
1324 
1325 	if (register_A & 0x01)
1326 	{
1327 		register_B += temp_word;
1328 		SETFC (register_B);
1329 		register_B &= 0x0FFF;
1330 	}
1331 	else
1332 	{
1333 		temp_word += register_B;
1334 		SETFC (temp_word);
1335 	}
1336 
1337 	return state_AA;
1338 }
1339 
1340   /* LSRe */
opLSRe_A_AA(int opcode)1341 CINESTATE opLSRe_A_AA (int opcode)
1342 {
1343 	/*
1344 	 * EB; right shift pure; fill new bit with zero.
1345 	 */
1346 
1347 	CINEWORD temp_word = 0x0BEB;
1348 
1349 	cmp_new = temp_word;
1350 	SETA0 (register_A);
1351 	cmp_old = register_A;
1352 
1353 	temp_word += register_A;
1354 	SETFC (temp_word);
1355 
1356 	register_A >>= 1;
1357 	return state_AA;
1358 }
1359 
opLSRe_B_AA(int opcode)1360 CINESTATE opLSRe_B_AA (int opcode)
1361 {
1362 	CINEWORD temp_word = 0x0BEB;
1363 
1364 	cmp_new = temp_word;
1365 	SETA0 (register_A);
1366 	cmp_old = register_B;
1367 
1368 	temp_word += register_B;
1369 	SETFC (temp_word);
1370 
1371 	register_B >>= 1;
1372 
1373 	return state_AA;
1374 }
1375 
opLSRf_A_AA(int opcode)1376 CINESTATE opLSRf_A_AA (int opcode)
1377 {
1378 	UNFINISHED ("opLSRf 1\n");
1379 	return state_AA;
1380 }
1381 
opLSRf_B_AA(int opcode)1382 CINESTATE opLSRf_B_AA (int opcode)
1383 {
1384 	UNFINISHED ("opLSRf 2\n");
1385 	return state_AA;
1386 }
1387 
opLSLe_A_AA(int opcode)1388 CINESTATE opLSLe_A_AA (int opcode)
1389 {
1390 	/*
1391 	 * EC; left shift pure; fill new bit with zero *
1392 	 */
1393 
1394 	CINEWORD temp_word = 0x0CEC;
1395 
1396 	cmp_new = temp_word;
1397 	SETA0 (register_A);
1398 	cmp_old = register_A;
1399 
1400 	temp_word += register_A;
1401 	SETFC (temp_word);
1402 
1403 	register_A <<= 1;
1404 	register_A &= 0x0FFF;
1405 
1406 	return state_AA;
1407 }
1408 
opLSLe_B_AA(int opcode)1409 CINESTATE opLSLe_B_AA (int opcode)
1410 {
1411 	CINEWORD temp_word = 0x0CEC;                          /* data register */
1412 
1413 	cmp_new = temp_word;                         /* magic value */
1414 	SETA0 (register_A);                        /* back up bit0 */
1415 	cmp_old = register_B;                        /* store old acc */
1416 
1417 	temp_word += register_B;                     /* add to acc */
1418 	SETFC (temp_word);                         /* store carry flag */
1419 	register_B <<= 1;                            /* add regA to itself */
1420 	register_B &= 0xFFF;                         /* toss excess bits */
1421 
1422 	return state_AA;
1423 }
1424 
opLSLf_A_AA(int opcode)1425 CINESTATE opLSLf_A_AA (int opcode)
1426 {
1427 	UNFINISHED ("opLSLf 1\n");
1428 	return state_AA;
1429 }
1430 
opLSLf_B_AA(int opcode)1431 CINESTATE opLSLf_B_AA (int opcode)
1432 {
1433 	UNFINISHED ("opLSLf 2\n");
1434 	return state_AA;
1435 }
1436 
opASRe_A_AA(int opcode)1437 CINESTATE opASRe_A_AA (int opcode)
1438 {
1439 	/* agh! I dislike these silly 12bit processors :P */
1440 
1441 	cmp_new = 0x0DED;
1442 	SETA0 (register_A);           /* store bit0 */
1443 	SETFC (register_A);
1444 	cmp_old = register_A;
1445 
1446 	register_A <<= 4; /* get sign bit */
1447 	register_A = SAR(register_A,5);
1448 	register_A &= 0xFFF;
1449 
1450 	return state_AA;
1451 }
1452 
opASRe_B_AA(int opcode)1453 CINESTATE opASRe_B_AA (int opcode)
1454 {
1455 	cmp_new = 0x0DED;
1456 	SETA0 (register_A);
1457 	SETFC (register_A);
1458 	cmp_old = register_B;
1459 
1460 	register_B <<= 4;
1461 	register_B = SAR(register_B,5);
1462 	register_B &= 0x0FFF;
1463 
1464 	return state_AA;
1465 }
1466 
opASRf_A_AA(int opcode)1467 CINESTATE opASRf_A_AA (int opcode)
1468 {
1469 	UNFINISHED ("opASRf 1\n");
1470 	return state_AA;
1471 }
1472 
opASRf_B_AA(int opcode)1473 CINESTATE opASRf_B_AA (int opcode)
1474 {
1475 	UNFINISHED ("opASRf 2\n");
1476 	return state_AA;
1477 }
1478 
opASRDe_A_AA(int opcode)1479 CINESTATE opASRDe_A_AA (int opcode)
1480 {
1481 	/*
1482 	 * Arithmetic shift right of D (A+B) .. B is high (sign bits).
1483 	 * divide by 2, but leave the sign bit the same. (ie: 1010 -> 1001)
1484 	 */
1485 	CINEWORD temp_word = 0x0EEE;
1486 	CINEWORD temp_word_2;
1487 
1488 	cmp_new = temp_word;          /* save new acc value */
1489 	SETA0 (register_A & 0xFF);  /* save old accA bit0 */
1490 	cmp_old = register_A;         /* save old acc */
1491 
1492 	temp_word += register_A;
1493 	SETFC (temp_word);
1494 
1495 	register_A <<= 4;
1496 	register_B <<= 4;
1497 
1498 	temp_word_2 = (register_B >> 4) << 15;
1499 	register_B = SAR(register_B,5);
1500 	register_A = (register_A >> 1) | temp_word_2;
1501 	register_A >>= 4;
1502 
1503 	register_B &= 0x0FFF;
1504 	return state_AA;
1505 }
1506 
opASRDe_B_AA(int opcode)1507 CINESTATE opASRDe_B_AA (int opcode)
1508 {
1509 	CINEWORD temp_word = 0x0EEE;
1510 
1511 	cmp_new = temp_word;
1512 	SETA0 (register_A & 0xFF);
1513 	cmp_old = register_B;
1514 
1515 	temp_word += register_B;
1516 	SETFC (temp_word);
1517 	register_B <<= 4;
1518 	register_B = SAR(register_B,5);
1519 	register_B &= 0x0FFF;
1520 
1521 	return state_AA;
1522 }
1523 
opASRDf_A_AA(int opcode)1524 CINESTATE opASRDf_A_AA (int opcode)
1525 {
1526 	UNFINISHED ("opASRDf 1\n");
1527 	return state_AA;
1528 }
1529 
opASRDf_B_AA(int opcode)1530 CINESTATE opASRDf_B_AA (int opcode)
1531 {
1532 	UNFINISHED ("opASRDf 2\n");
1533 	return state_AA;
1534 }
1535 
opLSLDe_A_AA(int opcode)1536 CINESTATE opLSLDe_A_AA (int opcode)
1537 {
1538 	/* LSLDe -- Left shift through both accumulators; lossy in middle. */
1539 
1540 	CINEWORD temp_word = 0x0FEF;
1541 
1542 	cmp_new = temp_word;
1543 	SETA0 (register_A);
1544 	cmp_old = register_A;
1545 
1546 	temp_word += register_A;
1547 	SETFC (temp_word);
1548 	register_A <<= 1;                             /* logical shift left */
1549 	register_A &= 0xFFF;
1550 
1551 	register_B <<= 1;
1552 	register_B &= 0xFFF;
1553 
1554 	return state_AA;
1555 }
1556 
opLSLDe_B_AA(int opcode)1557 CINESTATE opLSLDe_B_AA (int opcode)
1558 {
1559 	UNFINISHED ("opLSLD 1\n");
1560 	return state_AA;
1561 }
1562 
opLSLDf_A_AA(int opcode)1563 CINESTATE opLSLDf_A_AA (int opcode)
1564 {
1565 	/* LSLDf */
1566 
1567 	CINEWORD temp_word = 0x0FFF;
1568 
1569 	cmp_new = temp_word;
1570 	SETA0 (register_A);
1571 	cmp_old = register_A;
1572 
1573 	temp_word += register_A;
1574 	SETFC (temp_word);
1575 
1576 	register_A <<= 1;
1577 	register_A &= 0x0FFF;
1578 
1579 	register_B <<= 1;
1580 	register_B &= 0x0FFF;
1581 
1582 	return state_AA;
1583 }
1584 
opLSLDf_B_AA(int opcode)1585 CINESTATE opLSLDf_B_AA (int opcode)
1586 {
1587 	/* not 'the same' as the A->AA version above */
1588 
1589 	CINEWORD temp_word = 0x0FFF;
1590 
1591 	cmp_new = temp_word;
1592 	SETA0 (register_A);
1593 	cmp_old = register_B;
1594 
1595 	temp_word += register_B;
1596 	SETFC (temp_word);
1597 
1598 	register_B <<= 1;
1599 	register_B &= 0x0FFF;
1600 
1601 	return state_AA;
1602 }
1603 
opJMP_A_A(int opcode)1604 CINESTATE opJMP_A_A (int opcode)
1605 {
1606 	/*
1607 	 * simple jump; change PC and continue..
1608 	 */
1609 
1610 	JMP();
1611 	return state_A;
1612 }
1613 
opJMP_B_BB(int opcode)1614 CINESTATE opJMP_B_BB (int opcode)
1615 {
1616 	JMP();
1617 	return state_BB;
1618 }
1619 
opJEI_A_A(int opcode)1620 CINESTATE opJEI_A_A (int opcode)
1621 {
1622 	if (FromX & 0x800)
1623 		FromX |= 0xF000;
1624 	if (!(CCPU_READPORT (CCPU_PORT_IOOUTPUTS) & 0x80))
1625 	{
1626 		if ((CCPU_READPORT (CCPU_PORT_IN_JOYSTICKY) - (CINESWORD)FromX) < 0x800)
1627 			JMP();
1628 	}
1629 	else
1630 	{
1631 		if ((CCPU_READPORT (CCPU_PORT_IN_JOYSTICKX) - (CINESWORD)FromX) < 0x800)
1632 			JMP();
1633 	}
1634 
1635 	return state_A;
1636 }
1637 
opJEI_B_BB(int opcode)1638 CINESTATE opJEI_B_BB (int opcode)
1639 {
1640 	if (FromX & 0x800)
1641 		FromX |= 0xF000;
1642 	if (!(CCPU_READPORT (CCPU_PORT_IOOUTPUTS) & 0x80))
1643 	{
1644 		if ((CCPU_READPORT (CCPU_PORT_IN_JOYSTICKY) - (CINESWORD)FromX) < 0x800)
1645 			JMP();
1646 	}
1647 	else
1648 	{
1649 		if ((CCPU_READPORT (CCPU_PORT_IN_JOYSTICKX) - (CINESWORD)FromX) < 0x800)
1650 			JMP();
1651 	}
1652 
1653 	return state_BB;
1654 }
1655 
opJEI_A_B(int opcode)1656 CINESTATE opJEI_A_B (int opcode)
1657 {
1658 	if (FromX & 0x800)
1659 		FromX |= 0xF000;
1660 	if (!(CCPU_READPORT (CCPU_PORT_IOOUTPUTS) & 0x80))
1661 	{
1662 		if ((CCPU_READPORT (CCPU_PORT_IN_JOYSTICKY) - (CINESWORD)FromX) < 0x800)
1663 			JMP();
1664 	}
1665 	else
1666 	{
1667 		if ((CCPU_READPORT (CCPU_PORT_IN_JOYSTICKX) - (CINESWORD)FromX) < 0x800)
1668 			JMP();
1669 	}
1670 
1671 	return state_B;
1672 }
1673 
opJMI_A_A(int opcode)1674 CINESTATE opJMI_A_A (int opcode)
1675 {
1676 	/*
1677 	 * previous instruction was not an ACC instruction, nor was the
1678 	 * instruction twice back a USB, therefore minus flag test the
1679 	 * current A-reg
1680 	 */
1681 
1682 	/* negative acc? */
1683 	if (register_A & 0x800)
1684 		JMP();	  /* yes -- do jump */
1685 
1686 	return state_A;
1687 }
1688 
opJMI_AA_A(int opcode)1689 CINESTATE opJMI_AA_A (int opcode)
1690 {
1691 	/* previous acc negative? Jump if so... */
1692 	if (cmp_old & 0x800)
1693 		JMP();
1694 
1695 	return state_A;
1696 }
1697 
opJMI_BB_A(int opcode)1698 CINESTATE opJMI_BB_A (int opcode)
1699 {
1700 	if (register_B & 0x800)
1701 		JMP();
1702 
1703 	return state_A;
1704 }
1705 
opJMI_B_BB(int opcode)1706 CINESTATE opJMI_B_BB (int opcode)
1707 {
1708 	if (register_A & 0x800)
1709 		JMP();
1710 
1711 	return state_BB;
1712 }
1713 
opJLT_A_A(int opcode)1714 CINESTATE opJLT_A_A (int opcode)
1715 {
1716 	/* jump if old acc equals new acc */
1717 
1718 	if (cmp_new < cmp_old)
1719 		JMP();
1720 
1721 	return state_A;
1722 }
1723 
opJLT_B_BB(int opcode)1724 CINESTATE opJLT_B_BB (int opcode)
1725 {
1726 	if (cmp_new < cmp_old)
1727 		JMP();
1728 
1729 	return state_BB;
1730 }
1731 
opJEQ_A_A(int opcode)1732 CINESTATE opJEQ_A_A (int opcode)
1733 {
1734 	/* jump if equal */
1735 
1736 	if (cmp_new == cmp_old)
1737 		JMP();
1738 
1739 	return state_A;
1740 }
1741 
opJEQ_B_BB(int opcode)1742 CINESTATE opJEQ_B_BB (int opcode)
1743 {
1744 	if (cmp_new == cmp_old)
1745 		JMP();
1746 
1747 	return state_BB;
1748 }
1749 
opJA0_A_A(int opcode)1750 CINESTATE opJA0_A_A (int opcode)
1751 {
1752 	if (acc_a0 & 0x01)
1753 		JMP();
1754 
1755 	return state_A;
1756 }
1757 
opJA0_B_BB(int opcode)1758 CINESTATE opJA0_B_BB (int opcode)
1759 {
1760 	if (acc_a0 & 0x01)
1761 		JMP();
1762 
1763 	return state_BB;
1764 }
1765 
opJNC_A_A(int opcode)1766 CINESTATE opJNC_A_A (int opcode)
1767 {
1768 	if (!(GETFC() & 0xF0))
1769 		JMP(); /* no carry, so jump */
1770 
1771 	return state_A;
1772 }
1773 
opJNC_B_BB(int opcode)1774 CINESTATE opJNC_B_BB (int opcode)
1775 {
1776 	if (!(GETFC() & 0xF0))
1777 		JMP(); /* no carry, so jump */
1778 
1779 	return state_BB;
1780 }
1781 
opJDR_A_A(int opcode)1782 CINESTATE opJDR_A_A (int opcode)
1783 {
1784 	/*
1785 	 * Calculate number of cycles executed since
1786 	 * last 'VDR' instruction, add two and use as
1787 	 * cycle count, never branch
1788 	 */
1789 	return state_A;
1790 }
1791 
opJDR_B_BB(int opcode)1792 CINESTATE opJDR_B_BB (int opcode)
1793 {
1794 	/*
1795 	 * Calculate number of cycles executed since
1796 	 * last 'VDR' instruction, add two and use as
1797 	 * cycle count, never branch
1798 	 */
1799 	return state_BB;
1800 }
1801 
opNOP_A_A(int opcode)1802 CINESTATE opNOP_A_A (int opcode)
1803 {
1804 	return state_A;
1805 }
1806 
opNOP_B_BB(int opcode)1807 CINESTATE opNOP_B_BB (int opcode)
1808 {
1809 	return state_BB;
1810 }
1811 
opJPP32_A_B(int opcode)1812 CINESTATE opJPP32_A_B (int opcode)
1813 {
1814 	/*
1815 	 * 00 = Offset 0000h
1816 	 * 01 = Offset 1000h
1817 	 * 02 = Offset 2000h
1818 	 * 03 = Offset 3000h
1819 	 * 04 = Offset 4000h
1820 	 * 05 = Offset 5000h
1821 	 * 06 = Offset 6000h
1822 	 * 07 = Offset 7000h
1823 	 */
1824 	CINEWORD temp_word = (register_P & 0x07) << 12;  /* rom offset */
1825 	register_PC = register_J + temp_word;
1826 	return state_B;
1827 }
1828 
opJPP32_B_BB(int opcode)1829 CINESTATE opJPP32_B_BB (int opcode)
1830 {
1831 	CINEWORD temp_word = (register_P & 0x07) << 12;  /* rom offset */
1832 	register_PC = register_J + temp_word;
1833 	return state_BB;
1834 }
1835 
opJPP16_A_B(int opcode)1836 CINESTATE opJPP16_A_B (int opcode)
1837 {
1838 	/*
1839 	 * 00 = Offset 0000h
1840 	 * 01 = Offset 1000h
1841 	 * 02 = Offset 2000h
1842 	 * 03 = Offset 3000h
1843 	 */
1844 	CINEWORD temp_word = (register_P & 0x03) << 12;  /* rom offset */
1845 	register_PC = register_J + temp_word;
1846 	return state_B;
1847 }
1848 
opJPP16_B_BB(int opcode)1849 CINESTATE opJPP16_B_BB (int opcode)
1850 {
1851 	CINEWORD temp_word = (register_P & 0x03) << 12;  /* rom offset */
1852 	register_PC = register_J + temp_word;
1853 	return state_BB;
1854 }
1855 
opJMP_A_B(int opcode)1856 CINESTATE opJMP_A_B (int opcode)
1857 {
1858 	JMP();
1859 	return state_B;
1860 }
1861 
opJPP8_A_B(int opcode)1862 CINESTATE opJPP8_A_B (int opcode)
1863 {
1864 	/*
1865 	 * "long jump"; combine P and J to jump to a new far location (that can
1866 	 * 	be more than 12 bits in address). After this jump, further jumps
1867 	 * are local to this new page.
1868 	 */
1869 	CINEWORD temp_word = ((register_P & 0x03) - 1) << 12;  /* rom offset */
1870 	register_PC = register_J + temp_word;
1871 	return state_B;
1872 }
1873 
opJPP8_B_BB(int opcode)1874 CINESTATE opJPP8_B_BB (int opcode)
1875 {
1876 	CINEWORD temp_word = ((register_P & 0x03) - 1) << 12;  /* rom offset */
1877 	register_PC = register_J + temp_word;
1878 	return state_BB;
1879 }
1880 
opJMI_A_B(int opcode)1881 CINESTATE opJMI_A_B (int opcode)
1882 {
1883 	if (register_A & 0x800)
1884 		JMP();
1885 
1886 	return state_B;
1887 }
1888 
opJMI_AA_B(int opcode)1889 CINESTATE opJMI_AA_B (int opcode)
1890 {
1891 	UNFINISHED ("opJMI 3\n");
1892 	return state_B;
1893 }
1894 
opJMI_BB_B(int opcode)1895 CINESTATE opJMI_BB_B (int opcode)
1896 {
1897 	UNFINISHED ("opJMI 4\n");
1898 	return state_B;
1899 }
1900 
opJLT_A_B(int opcode)1901 CINESTATE opJLT_A_B (int opcode)
1902 {
1903 	if (cmp_new < cmp_old)
1904 		JMP();
1905 
1906 	return state_B;
1907 }
1908 
opJEQ_A_B(int opcode)1909 CINESTATE opJEQ_A_B (int opcode)
1910 {
1911 	if (cmp_new == cmp_old)
1912 		JMP();
1913 
1914 	return state_B;
1915 }
1916 
opJA0_A_B(int opcode)1917 CINESTATE opJA0_A_B (int opcode)
1918 {
1919 	if (GETA0() & 0x01)
1920 		JMP();
1921 
1922 	return state_B;
1923 }
1924 
opJNC_A_B(int opcode)1925 CINESTATE opJNC_A_B (int opcode)
1926 {
1927 	if (!(GETFC() & 0x0F0))
1928 		JMP(); /* if no carry, jump */
1929 
1930 	return state_B;
1931 }
1932 
opJDR_A_B(int opcode)1933 CINESTATE opJDR_A_B (int opcode)
1934 {
1935 	/* register_PC++; */
1936 	//logerror("The hell? No PC incrementing?\n");
1937 	return state_B;
1938 }
1939 
1940   /* NOP */
opNOP_A_B(int opcode)1941 CINESTATE opNOP_A_B (int opcode)
1942 {
1943 	return state_B;
1944 }
1945 
opLLT_A_AA(int opcode)1946 CINESTATE opLLT_A_AA (int opcode)
1947 {
1948 	CINEBYTE temp_byte = 0;
1949 
1950 	while (1)
1951 	{
1952 		CINEWORD temp_word = register_A >> 8;  /* register_A's high bits */
1953 		temp_word &= 0x0A;                   /* only want PA11 and PA9 */
1954 
1955 		if (temp_word)
1956 		{
1957 			temp_word ^= 0x0A;                   /* flip the bits */
1958 
1959 			if (temp_word)
1960 				break;                	        /* if not zero, mismatch found */
1961 		}
1962 
1963 		temp_word = register_B >> 8;         /* regB's top bits */
1964 		temp_word &= 0x0A;                   /* only want SA11 and SA9 */
1965 
1966 		if (temp_word)
1967 		{
1968 			temp_word ^= 0x0A;                   /* flip bits */
1969 
1970 			if (temp_word)
1971 				break;                          /* if not zero, mismatch found */
1972 		}
1973 
1974 		register_A <<= 1;                    /* shift regA */
1975 		register_B <<= 1;                    /* shift regB */
1976 
1977 		temp_byte ++;
1978 		if (!temp_byte)
1979 			return state_AA;
1980         /* try again */
1981 	}
1982 
1983 	vgShiftLength = temp_byte;
1984 	register_A &= 0x0FFF;
1985 	register_B &= 0x0FFF;
1986 	return state_AA;
1987 }
1988 
opLLT_B_AA(int opcode)1989 CINESTATE opLLT_B_AA (int opcode)
1990 {
1991 	UNFINISHED ("opLLT 1\n");
1992 	return state_AA;
1993 }
1994 
opVIN_A_A(int opcode)1995 CINESTATE opVIN_A_A (int opcode)
1996 {
1997 	/* set the starting address of a vector */
1998 
1999 	FromX = register_A & 0xFFF;            /* regA goes to x-coord */
2000 	FromY = register_B & 0xFFF;            /* regB goes to y-coord */
2001 
2002 	return state_A;
2003 }
2004 
opVIN_B_BB(int opcode)2005 CINESTATE opVIN_B_BB (int opcode)
2006 {
2007 	FromX = register_A & 0xFFF;            /* regA goes to x-coord */
2008 	FromY = register_B & 0xFFF;            /* regB goes to y-coord */
2009 
2010 	return state_BB;
2011 }
2012 
opWAI_A_A(int opcode)2013 CINESTATE opWAI_A_A (int opcode)
2014 {
2015 	/* wait for a tick on the watchdog */
2016 	bNewFrame = 1;
2017 	bailOut = TRUE;
2018 	return state;
2019 }
2020 
opWAI_B_BB(int opcode)2021 CINESTATE opWAI_B_BB (int opcode)
2022 {
2023 	bNewFrame = 1;
2024 	bailOut = TRUE;
2025 	return state;
2026 }
2027 
opVDR_A_A(int opcode)2028 CINESTATE opVDR_A_A (int opcode)
2029 {
2030 	/* set ending points and draw the vector, or buffer for a later draw. */
2031 	int ToX = register_A & 0xFFF;
2032 	int ToY = register_B & 0xFFF;
2033 
2034 	/*
2035 	 * shl 20, sar 20; this means that if the CCPU reg should be -ve,
2036 	 * we should be negative as well.. sign extended.
2037 	 */
2038 	if (FromX & 0x800)
2039 		FromX |= 0xFFFFF000;
2040 	if (ToX & 0x800)
2041 		ToX |= 0xFFFFF000;
2042 	if (FromY & 0x800)
2043 		FromY |= 0xFFFFF000;
2044 	if (ToY & 0x800)
2045 		ToY |= 0xFFFFF000;
2046 
2047 	/* figure out the vector */
2048 	ToX -= FromX;
2049 	ToX = SAR(ToX,vgShiftLength);
2050 	ToX += FromX;
2051 
2052 	ToY -= FromY;
2053 	ToY = SAR(ToY,vgShiftLength);
2054 	ToY += FromY;
2055 
2056 	/* do orientation flipping, etc. */
2057 	/* NOTE: this has been removed on the assumption that the vector draw routine can do it all */
2058 #if !RAW_VECTORS
2059 	if (bFlipX)
2060 	{
2061 		ToX = sdwGameXSize - ToX;
2062 		FromX = sdwGameXSize - FromX;
2063 	}
2064 
2065 	if (bFlipY)
2066 	{
2067 		ToY = sdwGameYSize - ToY;
2068 		FromY = sdwGameYSize - FromY;
2069 	}
2070 
2071 	FromX += sdwXOffset;
2072 	ToX += sdwXOffset;
2073 
2074 	FromY += sdwYOffset;
2075 	ToY += sdwYOffset;
2076 
2077 	/* check real coords */
2078 	if (bSwapXY)
2079 	{
2080 		CINEWORD temp_word;
2081 
2082 		temp_word = ToY;
2083 		ToY = ToX;
2084 		ToX = temp_word;
2085 
2086 		temp_word = FromY;
2087 		FromY = FromX;
2088 		FromX = temp_word;
2089 	}
2090 #endif
2091 
2092 	/* render the line */
2093 	CinemaVectorData (FromX, FromY, ToX, ToY, vgColour);
2094 
2095 	return state_A;
2096 }
2097 
opVDR_B_BB(int opcode)2098 CINESTATE opVDR_B_BB (int opcode)
2099 {
2100 	UNFINISHED ("opVDR B 1\n");
2101 	return state_BB;
2102 }
2103 
2104 /*
2105  * some code needs to be changed based on the machine or switches set.
2106  * Instead of getting disorganized, I'll put the extra dispatchers
2107  * here. The main dispatch loop jumps here, checks options, and
2108  * redispatches to the actual opcode handlers.
2109  */
2110 
2111 /* JPP series of opcodes */
tJPP_A_B(int opcode)2112 CINESTATE tJPP_A_B (int opcode)
2113 {
2114 	/* MSIZE -- 0 = 4k, 1 = 8k, 2 = 16k, 3 = 32k */
2115 	switch (ccpu_msize)
2116 	{
2117 		case CCPU_MEMSIZE_4K:
2118 		case CCPU_MEMSIZE_8K:
2119 			return opJPP8_A_B (opcode);
2120 		case CCPU_MEMSIZE_16K:
2121 			return opJPP16_A_B (opcode);
2122 		case CCPU_MEMSIZE_32K:
2123 			return opJPP32_A_B (opcode);
2124 	}
2125 	//logerror("Out of range JPP!\n");
2126 	return opJPP32_A_B (opcode);
2127 }
2128 
tJPP_B_BB(int opcode)2129 CINESTATE tJPP_B_BB (int opcode)
2130 {
2131 	/* MSIZE -- 0 = 4k, 1 = 8k, 2 = 16k, 3 = 32k */
2132 	switch (ccpu_msize)
2133 	{
2134 		case CCPU_MEMSIZE_4K:
2135 		case CCPU_MEMSIZE_8K:
2136 			return opJPP8_B_BB (opcode);
2137 		case CCPU_MEMSIZE_16K:
2138 			return opJPP16_B_BB (opcode);
2139 		case CCPU_MEMSIZE_32K:
2140 			return opJPP32_B_BB (opcode);
2141 	}
2142 	//logerror("Out of range JPP!\n");
2143 	return state;
2144 }
2145 
2146 /* JMI series of opcodes */
2147 
tJMI_A_B(int opcode)2148 CINESTATE tJMI_A_B (int opcode)
2149 {
2150 	return (ccpu_jmi_dip) ? opJMI_A_B (opcode) : opJEI_A_B (opcode);
2151 }
2152 
tJMI_A_A(int opcode)2153 CINESTATE tJMI_A_A (int opcode)
2154 {
2155 	return (ccpu_jmi_dip) ? opJMI_A_A (opcode) : opJEI_A_A (opcode);
2156 }
2157 
tJMI_AA_B(int opcode)2158 CINESTATE tJMI_AA_B (int opcode)
2159 {
2160 	return (ccpu_jmi_dip) ? opJMI_AA_B (opcode) : opJEI_AA_B (opcode);
2161 }
2162 
tJMI_AA_A(int opcode)2163 CINESTATE tJMI_AA_A (int opcode)
2164 {
2165 	return (ccpu_jmi_dip) ? opJMI_AA_A (opcode) : opJEI_A_A (opcode);
2166 }
2167 
tJMI_B_BB1(int opcode)2168 CINESTATE tJMI_B_BB1 (int opcode)
2169 {
2170 	return (ccpu_jmi_dip) ? opJMI_B_BB (opcode) : opJEI_B_BB (opcode);
2171 }
2172 
tJMI_BB_B(int opcode)2173 CINESTATE tJMI_BB_B (int opcode)
2174 {
2175 	return (ccpu_jmi_dip) ? opJMI_BB_B (opcode) : opJEI_A_B (opcode);
2176 }
2177 
tJMI_BB_A(int opcode)2178 CINESTATE tJMI_BB_A (int opcode)
2179 {
2180 	return (ccpu_jmi_dip) ? opJMI_BB_A (opcode) : opJEI_A_A (opcode);
2181 }
2182 
2183 /*
2184  * OUT series of opcodes:
2185  * ccpu_monitor can be one of:
2186  * 1 -- 16-level colour
2187  * 2 -- 64-level colour
2188  * 3 -- War of the Worlds colour
2189  * other -- bi-level
2190  */
tOUT_A_A(int opcode)2191 CINESTATE tOUT_A_A (int opcode)
2192 {
2193 	switch (ccpu_monitor)
2194 	{
2195 		case CCPU_MONITOR_16LEV:
2196 			return opOUT16_A_A (opcode);
2197 		case CCPU_MONITOR_64LEV:
2198 			return opOUT64_A_A (opcode);
2199 		case CCPU_MONITOR_WOWCOL:
2200 			return opOUTWW_A_A (opcode);
2201 		default:
2202 			return opOUTbi_A_A (opcode);
2203 	}
2204 }
2205 
tOUT_B_BB(int opcode)2206 CINESTATE tOUT_B_BB (int opcode)
2207 {
2208 	switch (ccpu_monitor)
2209 	{
2210 		case CCPU_MONITOR_16LEV:
2211 			return opOUT16_B_BB (opcode);
2212 		case CCPU_MONITOR_64LEV:
2213 			return opOUT64_B_BB (opcode);
2214 		case CCPU_MONITOR_WOWCOL:
2215 			return opOUTWW_B_BB (opcode);
2216 		default:
2217 			return opOUTbi_B_BB (opcode);
2218 	}
2219 }
2220 
2221 /* Reset C-CPU registers, flags, etc to default starting values
2222  */
cineReset(void)2223 void cineReset(void)
2224 {
2225 	/* zero registers */
2226 	register_PC = 0;
2227 	register_A = 0;
2228 	register_B = 0;
2229 	register_I = 0;
2230 	register_J = 0;
2231 	register_P = 0;
2232 	FromX = 0;
2233 	FromY = 0;
2234 	register_T = 0;
2235 
2236 	/* zero flags */
2237 	flag_C = 0;
2238 
2239 	/* reset state */
2240 	state = state_A;
2241 
2242 	/* reset RAM */
2243 	memset(ram, 0, sizeof(ram));
2244 
2245 	/* reset internal state */
2246 	cmp_old = 0;
2247 	cmp_new = 0;
2248 	SETA0 (0);
2249 }
2250 
cineSetJMI(int j)2251 void cineSetJMI(int j)
2252 {
2253 	ccpu_jmi_dip = j;
2254 /*
2255 	if (ccpu_jmi_dip)
2256 		fprintf (stderr, "CCPU JMI Set: Yes.\n");
2257 	else
2258 		fprintf (stderr, "CCPU JMI Set: No.\n");
2259 */
2260 }
2261 
cineSetMSize(int m)2262 void cineSetMSize(int m)
2263 {
2264 	ccpu_msize = m;
2265 /*
2266 	switch (m)
2267 	{
2268 		case 0:
2269 			fprintf (stderr, "CCPU Address Space: 4k\n");
2270 			break;
2271 		case 1:
2272 			fprintf (stderr, "CCPU Address Space: 8k\n");
2273 			break;
2274 		case 2:
2275 			fprintf (stderr, "CCPU Address Space: 16k\n");
2276 			break;
2277 		case 3:
2278 			fprintf (stderr, "CCPU Address Space: 32k\n");
2279 			break;
2280 		default:
2281 			fprintf (stderr, "CCPU Address Space: Error\n");
2282 			break;
2283 	}
2284 */
2285 }
2286 
cineSetMonitor(int m)2287 void cineSetMonitor(int m)
2288 {
2289 	ccpu_monitor = m;
2290 /*
2291 	switch (m)
2292 	{
2293 		case 1:
2294 			fprintf (stderr, "CCPU Monitor: 16-colour\n");
2295 			break;
2296 		case 2:
2297 			fprintf (stderr, "CCPU Monitor: 64-colour\n");
2298 			break;
2299 		case 3:
2300 			fprintf (stderr, "CCPU Monitor: War-of-the-Worlds-colour\n");
2301 			break;
2302 		default:
2303 			fprintf (stderr, "CCPU Monitor: bi-level-display\n");
2304 			break;
2305 	}
2306 */
2307 }
2308 
cSetContext(CONTEXTCCPU * c)2309 void cSetContext(CONTEXTCCPU *c)
2310 {
2311 	cmp_old = c -> accVal;
2312 	cmp_new = c -> cmpVal;
2313 	SETA0 (c -> pa0);
2314 	flag_C = c -> cFlag;
2315 	register_PC = c -> eRegPC;
2316 	register_A = c -> eRegA;
2317 	register_B = c -> eRegB;
2318 	register_I = c -> eRegI;
2319 	register_J = c -> eRegJ;
2320 	register_P = c -> eRegP;
2321 	state = (CINESTATE)c -> eCState;
2322 }
2323 
cGetContext(CONTEXTCCPU * c)2324 void cGetContext(CONTEXTCCPU *c)
2325 {
2326 	c -> accVal = cmp_old;
2327 	c -> cmpVal = cmp_new;
2328 	c -> pa0 = GETA0();
2329 	c -> cFlag = GETFC();
2330 	c -> eRegPC = register_PC;
2331 	c -> eRegA = register_A;
2332 	c -> eRegB = register_B;
2333 	c -> eRegI = register_I;
2334 	c -> eRegJ = register_J;
2335 	c -> eRegP = register_P;
2336 	c -> eCState = state;
2337 }
2338