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