1 //
2 // /home/ms/source/sidplay/libsidplay/emu/RCS/6510_.cpp,v
3 //
4 // --------------------------------------------------------------------------
5 // Copyright (c) 1994-1997 Michael Schwendt. All rights reserved.
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 2 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 //
21 // THIS SOFTWARE  IS PROVIDED  BY THE  AUTHOR ``AS  IS'' AND  ANY EXPRESS OR
22 // IMPLIED  WARRANTIES,  INCLUDING,   BUT  NOT  LIMITED   TO,  THE   IMPLIED
23 // WARRANTIES OF MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR PURPOSE  ARE
24 // DISCLAIMED.  IN NO EVENT SHALL  THE AUTHOR OR CONTRIBUTORS BE LIABLE  FOR
25 // ANY DIRECT,  INDIRECT, INCIDENTAL,  SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS
27 // OR SERVICES;  LOSS OF  USE, DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION)
28 // HOWEVER  CAUSED  AND  ON  ANY  THEORY  OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  IN
30 // ANY  WAY  OUT  OF  THE  USE  OF  THIS  SOFTWARE,  EVEN  IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 // --------------------------------------------------------------------------
33 //
34 // MOS-6510 Interpreter. Known bugs, missing features, incompatibilities:
35 //
36 //  - No support for code execution in Basic-ROM/Kernal-ROM.
37 //    Only execution of code in RAM is allowed.
38 //  - Probably inconsistent emulation of illegal instructions part 3.
39 //  - No detection of deadlocks.
40 //  - Faked RTI (= RTS).
41 //  - Anybody knows, whether it is ``Kernel'' instead of ``Kernal'' ?
42 //    Perhaps it is a proper name invented by CBM ?
43 //    It is spelled ``Kernal'' in nearly every C64 documentation !
44 //
45 
46 #include "compconf.h"
47 #ifdef SID_HAVE_EXCEPTIONS
48 #include <new>
49 #endif
50 #include "6510_.h"
51 #include "myendian.h"
52 #include "emucfg.h"
53 
54 
55 ubyte* c64mem1 = 0;               // 64KB C64-RAM
56 ubyte* c64mem2 = 0;               // Basic-ROM, VIC, SID, I/O, Kernal-ROM
57 bool sidKeysOff[32];              // key_off detection
58 bool sidKeysOn[32];               // key_on detection
59 ubyte sidLastValue = 0;           // last value written to the SID
60 ubyte optr3readWave = 0;          // D41B
61 ubyte optr3readEnve = 0;          // D41C
62 
63 // --------------------------------------------------------------------------
64 
65 static ubyte AC, XR, YR;          // 6510 processor registers
66 static uword PC, SP;              // program-counter, stack-pointer
67 // PC is only used temporarily !
68 // The current program-counter is pPC-pPCbase
69 
70 static ubyte* pPCbase;            // pointer to RAM/ROM buffer base
71 static ubyte* pPCend;             // pointer to RAM/ROM buffer end
72 static ubyte* pPC;                // pointer to PC location
73 
74 // ---------------------------------------------------- Memory de-/allocation
75 
76 static ubyte* c64ramBuf = 0;
77 static ubyte* c64romBuf = 0;
78 
c64memFree()79 bool c64memFree()
80 {
81 	if ( c64romBuf != 0 )
82 	{
83 		delete[] c64romBuf;
84 		c64romBuf = (c64mem2 = 0);
85 	}
86 	if ( c64ramBuf != 0 )
87 	{
88 		delete[] c64ramBuf;
89 		c64ramBuf = (c64mem1 = 0);
90 	}
91 	return true;
92 }
93 
c64memAlloc()94 bool c64memAlloc()
95 {
96 	c64memFree();
97 	bool wasSuccess = true;
98 #ifdef SID_HAVE_EXCEPTIONS
99 	if (( c64ramBuf = new(std::nothrow) ubyte[65536+256] ) == 0 )
100 #else
101 	if (( c64ramBuf = new ubyte[65536+256] ) == 0 )
102 #endif
103 	{
104 		wasSuccess = false;
105 	}
106 #ifdef SID_HAVE_EXCEPTIONS
107 	if (( c64romBuf = new(std::nothrow) ubyte[65536+256] ) == 0 )
108 #else
109 	if (( c64romBuf = new ubyte[65536+256] ) == 0 )
110 #endif
111 	{
112 		wasSuccess = false;
113 	}
114 	if (!wasSuccess)
115 	{
116 		c64memFree();
117 	}
118 	else
119 	{
120 		// Make the memory buffers accessible to the whole emulator engine.
121 		c64mem1 = c64ramBuf;
122 		c64mem2 = c64romBuf;
123 	}
124 	return wasSuccess;
125 }
126 
127 // ------------------------------------------------------ (S)tatus (R)egister
128 // MOS-6510 SR: NV-BDIZC
129 //              76543210
130 //
131 
132 struct statusRegister
133 {
134 	unsigned Carry     : 1;
135 	unsigned Zero      : 1;
136 	unsigned Interrupt : 1;
137 	unsigned Decimal   : 1;
138 	unsigned Break     : 1;
139 	unsigned NotUsed   : 1;
140 	unsigned oVerflow  : 1;
141 	unsigned Negative  : 1;
142 };
143 
144 static statusRegister SR;
145 
146 // Some handy defines to ease SR access.
147 #define CF SR.Carry
148 #define ZF SR.Zero
149 #define IF SR.Interrupt
150 #define DF SR.Decimal
151 #define BF SR.Break
152 #define NU SR.NotUsed
153 #define VF SR.oVerflow
154 #define NF SR.Negative
155 
affectNZ(ubyte reg)156 inline void affectNZ(ubyte reg)
157 {
158 	ZF = (reg == 0);
159 	NF = ((reg & 0x80) != 0);
160 }
161 
resetSR()162 inline void resetSR()
163 {
164 	// Explicit paranthesis looks great.
165 	CF = (ZF = (IF = (DF = (BF = (VF = (NF = 0))))));
166 	NU = 1;
167 }
168 
codeSR()169 inline ubyte codeSR()
170 {
171 	register ubyte tempSR = CF;
172 	tempSR |= (ZF<<1);
173 	tempSR |= (IF<<2);
174 	tempSR |= (DF<<3);
175 	tempSR |= (BF<<4);
176 	tempSR |= (NU<<5);
177 	tempSR |= (VF<<6);
178 	tempSR |= (NF<<7);
179 	return tempSR;
180 }
181 
decodeSR(ubyte stackByte)182 inline void decodeSR(ubyte stackByte)
183 {
184 	CF = (stackByte & 1);
185 	ZF = ((stackByte & 2) !=0 );
186 	IF = ((stackByte & 4) !=0 );
187 	DF = ((stackByte & 8) !=0 );
188 	BF = ((stackByte & 16) !=0 );
189 	NU = 1;  // if used or writable, ((stackByte & 32) !=0 );
190 	VF = ((stackByte & 64) !=0 );
191 	NF = ((stackByte & 128) !=0 );
192 }
193 
194 // --------------------------------------------------------------------------
195 // Handling conditional branches.
196 
branchIfClear(ubyte flag)197 inline void branchIfClear(ubyte flag)
198 {
199 	if (flag == 0)
200 	{
201 		PC = pPC-pPCbase;   // calculate 16-bit PC
202 		PC += (sbyte)*pPC;  // add offset, keep it 16-bit (uword)
203 		pPC = pPCbase+PC;   // calc new pointer-PC
204 	}
205 	pPC++;
206 }
207 
branchIfSet(ubyte flag)208 inline void branchIfSet(ubyte flag)
209 {
210 	if (flag != 0)
211 	{
212 		PC = pPC-pPCbase;   // calculate 16-bit PC
213 		PC += (sbyte)*pPC;  // add offset, keep it 16-bit (uword)
214 		pPC = pPCbase+PC;   // calc new pointer-PC
215 	}
216 	pPC++;
217 }
218 
219 // --------------------------------------------------------------------------
220 // Addressing modes:
221 // Calculating 8/16-bit effective addresses out of data operands.
222 
abso()223 inline uword abso()
224 {
225 	return readLEword(pPC);
226 }
227 
absx()228 inline uword absx()
229 {
230 	return readLEword(pPC)+XR;
231 }
232 
absy()233 inline uword absy()
234 {
235 	return readLEword(pPC)+YR;
236 }
237 
imm()238 inline ubyte imm()
239 {
240 	return *pPC;
241 }
242 
indx()243 inline uword indx()
244 {
245 	return readEndian(c64mem1[(*pPC+1+XR)&0xFF],c64mem1[(*pPC+XR)&0xFF]);
246 }
247 
indy()248 inline uword indy()
249 {
250 	return YR+readEndian(c64mem1[(*pPC+1)&0xFF],c64mem1[*pPC]);
251 }
252 
zp()253 inline ubyte zp()
254 {
255 	return *pPC;
256 }
257 
zpx()258 inline ubyte zpx()
259 {
260 	return *pPC+XR;
261 }
262 
zpy()263 inline ubyte zpy()
264 {
265 	return *pPC+YR;
266 }
267 
268 // --------------------------------------------------------------------------
269 // LIFO-Stack:
270 //
271 // |xxxxxx|
272 // |xxxxxx|
273 // |______|<- SP <= (hi)-return-address
274 // |______|      <= (lo)
275 // |______|
276 //
277 
278 static bool stackIsOkay = true;
279 
resetSP()280 inline void resetSP()
281 {
282 	SP = 0x1ff;          // SP to top of stack
283 	stackIsOkay = true;
284 }
285 
checkSP()286 inline void checkSP()
287 {
288 	stackIsOkay = ((SP>0xff)&&(SP<=0x1ff));  // check boundaries
289 }
290 
RTS_()291 inline void RTS_()
292 {
293     SP++;
294     PC =readEndian( c64mem1[SP +1], c64mem1[SP] ) +1;
295     pPC = pPCbase+PC;
296     SP++;
297     checkSP();
298 }
299 
300 // --------------------------------------------------------------------------
301 // Relevant configurable memory banks:
302 //
303 //  $A000 to $BFFF = RAM, Basic-ROM
304 //  $C000 to $CFFF = RAM
305 //  $D000 to $DFFF = RAM, I/O, Char-ROM
306 //  $E000 to $FFFF = RAM, Kernal-ROM
307 //
308 // Bank-Select Register $01:
309 //
310 //   Bits
311 //   210    $A000-$BFFF   $D000-$DFFF   $E000-$FFFF
312 //  ------------------------------------------------
313 //   000       RAM           RAM            RAM
314 //   001       RAM        Char-ROM          RAM
315 //   010       RAM        Char-ROM      Kernal-ROM
316 //   011    Basic-ROM     Char-ROM      Kernal-ROM
317 //   100       RAM           RAM            RAM
318 //   101       RAM           I/O            RAM
319 //   110       RAM           I/O        Kernal-ROM
320 //   111    Basic-ROM        I/O        Kernal-ROM
321 //
322 // "Transparent ROM" mode:
323 //
324 // Basic-ROM and Kernal-ROM are considered transparent to read/write access.
325 // Basic-ROM is also considered transparent to branches (JMP, BCC, ...).
326 // I/O and Kernal-ROM are togglable via bank-select register $01.
327 
328 static bool isBasic;   // these flags are used to not have to repeatedly
329 static bool isIO;      // evaluate the bank-select register for each
330 static bool isKernal;  // address operand
331 
332 static ubyte* bankSelReg;  // pointer to RAM[1], bank-select register
333 
334 static udword fakeReadTimer;
335 
336 
evalBankSelect()337 inline void evalBankSelect()
338 {
339 	// Determine new memory configuration.
340 	isBasic = ((*bankSelReg & 3) == 3);
341 	isIO = ((*bankSelReg & 7) > 4);
342 	isKernal = ((*bankSelReg & 2) != 0);
343 }
344 
345 
346 // Upon JMP/JSR prevent code execution in Basic-ROM/Kernal-ROM.
evalBankJump()347 inline void evalBankJump()
348 {
349 	if (PC < 0xA000)
350 	{
351 		;
352 	}
353 	else
354 	{
355 		// Get high-nibble of address.
356 		switch (PC >> 12)
357 		{
358 		 case 0xa:
359 		 case 0xb:
360 			{
361 				if (isBasic)
362 				{
363 					RTS_();
364 				}
365 				break;
366 			}
367 		 case 0xc:
368 			{
369 				break;
370 			}
371 		 case 0xd:
372 			{
373 				if (isIO)
374 				{
375 					RTS_();
376 				}
377 				break;
378 			}
379 		 case 0xe:
380 		 case 0xf:
381 		 default:  // <-- just to please the compiler
382 			{
383 				if (isKernal)
384 				{
385 					RTS_();
386 				}
387 				break;
388 			}
389 		}
390 	}
391 }
392 
393 
394 // Functions to retrieve data.
395 
readData_bs(uword addr)396 static ubyte readData_bs(uword addr)
397 {
398 	if (addr < 0xA000)
399 	{
400 		return c64mem1[addr];
401 	}
402 	else
403 	{
404 		// Get high-nibble of address.
405 		switch (addr >> 12)
406 		{
407 		 case 0xa:
408 		 case 0xb:
409 			{
410 				if (isBasic)
411 					return c64mem2[addr];
412 				else
413 					return c64mem1[addr];
414 			}
415 		 case 0xc:
416 			{
417 				return c64mem1[addr];
418 			}
419 		 case 0xd:
420 			{
421 				if (isIO)
422 				{
423 					uword tempAddr = (addr & 0xfc1f);
424 					// Not SID ?
425 					if (( tempAddr & 0xff00 ) != 0xd400 )
426 					{
427 						switch (addr)
428 						{
429 						 case 0xd011:
430 						 case 0xd012:
431 						 case 0xdc04:
432 						 case 0xdc05:
433 							{
434                                 fakeReadTimer = fakeReadTimer*13+1;
435 								return (ubyte)(fakeReadTimer>>3);
436 							}
437 						 default:
438 							{
439 								return c64mem2[addr];
440 							}
441 						}
442 					}
443 					else
444 					{
445 						// $D41D/1E/1F, $D43D/, ... SID not mirrored
446 						if (( tempAddr & 0x00ff ) >= 0x001d )
447 							return(c64mem2[addr]);
448 						// (Mirrored) SID.
449 						else
450 						{
451 							switch (tempAddr)
452 							{
453 							 case 0xd41b:
454 								{
455 									return optr3readWave;
456 								}
457 							 case 0xd41c:
458 								{
459 									return optr3readEnve;
460 								}
461 							 default:
462 								{
463 									return sidLastValue;
464 								}
465 							}
466 						}
467 					}
468 				}
469 				else
470 					return c64mem1[addr];
471 			}
472 		 case 0xe:
473 		 case 0xf:
474 		 default:  // <-- just to please the compiler
475 			{
476 				if (isKernal)
477 					return c64mem2[addr];
478 				else
479 					return c64mem1[addr];
480 			}
481 		}
482 	}
483 }
484 
readData_transp(uword addr)485 static ubyte readData_transp(uword addr)
486 {
487 	if (addr < 0xD000)
488 	{
489 		return c64mem1[addr];
490 	}
491 	else
492 	{
493 		// Get high-nibble of address.
494 		switch (addr >> 12)
495 		{
496 		 case 0xd:
497 			{
498 				if (isIO)
499 				{
500 					uword tempAddr = (addr & 0xfc1f);
501 					// Not SID ?
502 					if (( tempAddr & 0xff00 ) != 0xd400 )
503 					{
504 						switch (addr)
505 						{
506 						 case 0xd011:
507 						 case 0xd012:
508 						 case 0xdc04:
509 						 case 0xdc05:
510 							{
511                                 fakeReadTimer = fakeReadTimer*13+1;
512 								return (ubyte)(fakeReadTimer>>3);
513 							}
514 						 default:
515 							{
516 								return c64mem2[addr];
517 							}
518 						}
519 					}
520 					else
521 					{
522 						// $D41D/1E/1F, $D43D/, ... SID not mirrored
523 						if (( tempAddr & 0x00ff ) >= 0x001d )
524 							return(c64mem2[addr]);
525 						// (Mirrored) SID.
526 						else
527 						{
528 							switch (tempAddr)
529 							{
530 							 case 0xd41b:
531 								{
532 									return optr3readWave;
533 								}
534 							 case 0xd41c:
535 								{
536 									return optr3readEnve;
537 								}
538 							 default:
539 								{
540 									return sidLastValue;
541 								}
542 							}
543 						}
544 					}
545 				}
546 				else
547 					return c64mem1[addr];
548 			}
549 		 case 0xe:
550 		 case 0xf:
551 		 default:  // <-- just to please the compiler
552 			{
553 				return c64mem1[addr];
554 			}
555 		}
556 	}
557 }
558 
readData_plain(uword addr)559 static ubyte readData_plain(uword addr)
560 {
561 	return c64mem1[addr];
562 }
563 
readData_zp(uword addr)564 inline ubyte readData_zp(uword addr)
565 {
566 	return c64mem1[addr];
567 }
568 
569 
570 // Functions to store data.
571 
writeData_bs(uword addr,ubyte data)572 static void writeData_bs(uword addr, ubyte data)
573 {
574 	if ((addr < 0xd000) || (addr >= 0xe000))
575 	{
576 		c64mem1[addr] = data;
577 		if (addr == 0x01)  // write to Bank-Select Register ?
578 		{
579 			evalBankSelect();
580 		}
581 	}
582 	else
583 	{
584 		if (isIO)
585 		{
586 			// Check whether real SID or mirrored SID.
587 			uword tempAddr = (addr & 0xfc1f);
588 			// Not SID ?
589 			if (( tempAddr & 0xff00 ) != 0xd400 )
590 			{
591 				c64mem2[addr] = data;
592 			}
593 			// $D41D/1E/1F, $D43D/3E/3F, ...
594 			// Map to real address to support PlaySID
595 			// Extended SID Chip Registers.
596 			else if (( tempAddr & 0x00ff ) >= 0x001d )
597 			{
598 				// Mirrored SID.
599 				c64mem2[addr] = (sidLastValue = data);
600 			}
601 			else
602 			{
603 				// SID.
604 				c64mem2[tempAddr] = (sidLastValue = data);
605 				// Handle key_ons.
606 				sidKeysOn[tempAddr&0x001f] = sidKeysOn[tempAddr&0x001f] || ((data&1)!=0);
607 				// Handle key_offs.
608 				sidKeysOff[tempAddr&0x001f] = sidKeysOff[tempAddr&0x001f] || ((data&1)==0);
609 			}
610 		}
611 		else
612 		{
613 			c64mem1[addr] = data;
614 		}
615 	}
616 }
617 
writeData_plain(uword addr,ubyte data)618 static void writeData_plain(uword addr, ubyte data)
619 {
620 	// Check whether real SID or mirrored SID.
621 	uword tempAddr = (addr & 0xfc1f);
622 	// Not SID ?
623 	if (( tempAddr & 0xff00 ) != 0xd400 )
624 	{
625 		c64mem1[addr] = data;
626 	}
627 	// $D41D/1E/1F, $D43D/3E/3F, ...
628 	// Map to real address to support PlaySID
629 	// Extended SID Chip Registers.
630 	else if (( tempAddr & 0x00ff ) >= 0x001d )
631 	{
632 		// Mirrored SID.
633 		c64mem1[addr] = (sidLastValue = data);
634 	}
635 	else
636 	{
637 		// SID.
638 		c64mem2[tempAddr] = (sidLastValue = data);
639 		// Handle key_ons.
640 		sidKeysOn[tempAddr&0x001f] = sidKeysOn[tempAddr&0x001f] || ((data&1)!=0);
641 		// Handle key_offs.
642 		sidKeysOff[tempAddr&0x001f] = sidKeysOff[tempAddr&0x001f] || ((data&1)==0);
643 	}
644 }
645 
writeData_zp(uword addr,ubyte data)646 inline void writeData_zp(uword addr, ubyte data)
647 {
648 	c64mem1[addr] = data;
649 	if (addr == 0x01)  // write to Bank-Select Register ?
650 	{
651 		evalBankSelect();
652 	}
653 }
654 
655 
656 // Use pointers to allow plain-memory modifications.
657 static ubyte (*readData)(uword) = &readData_bs;
658 static void (*writeData)(uword,ubyte) = &writeData_bs;
659 
660 // --------------------------------------------------------------------------
661 // Legal instructions in alphabetical order.
662 //
663 
ADC_m(ubyte x)664 inline void ADC_m(ubyte x)
665 {
666 	if ( DF == 1 )
667 	{
668 		uword AC2 = AC +x +CF;
669 		ZF = ( AC2 == 0 );
670 		if ((( AC & 15 ) + ( x & 15 ) + CF ) > 9 )
671 		{
672 			AC2 += 6;
673 		}
674 		VF = ((( AC ^ x ^ AC2 ) & 0x80 ) != 0 ) ^ CF;
675 		NF = (( AC2 & 128 ) != 0 );
676 		if ( AC2 > 0x99 )
677 		{
678 			AC2 += 96;
679 		}
680 		CF = ( AC2 > 0x99 );
681 		AC = ( AC2 & 255 );
682 	}
683 	else
684 	{
685 		uword AC2 = AC +x +CF;
686 		CF = ( AC2 > 255 );
687 		VF = ((( AC ^ x ^ AC2 ) & 0x80 ) != 0 ) ^ CF;
688 		affectNZ( AC = ( AC2 & 255 ));
689 	}
690 }
ADC_imm()691 static void ADC_imm()  { ADC_m(imm()); pPC++; }
ADC_abso()692 static void ADC_abso()  { ADC_m( readData(abso()) ); pPC += 2; }
ADC_absx()693 static void ADC_absx()  { ADC_m( readData(absx()) ); pPC += 2; }
ADC_absy()694 static void ADC_absy()  { ADC_m( readData(absy()) ); pPC += 2; }
ADC_indx()695 static void ADC_indx()  { ADC_m( readData(indx()) ); pPC++; }
ADC_indy()696 static void ADC_indy()  { ADC_m( readData(indy()) ); pPC++; }
ADC_zp()697 static void ADC_zp()  { ADC_m( readData_zp(zp()) ); pPC++; }
ADC_zpx()698 static void ADC_zpx()  { ADC_m( readData_zp(zpx()) ); pPC++; }
699 
700 
AND_m(ubyte x)701 inline void AND_m(ubyte x)
702 {
703 	affectNZ( AC &= x );
704 }
AND_imm()705 static void AND_imm()  { AND_m(imm()); pPC++; }
AND_abso()706 static void AND_abso()  { AND_m( readData(abso()) ); pPC += 2; }
AND_absx()707 static void AND_absx()  { AND_m( readData(absx()) ); pPC += 2; }
AND_absy()708 static void AND_absy()  { AND_m( readData(absy()) ); pPC += 2; }
AND_indx()709 static void AND_indx()  { AND_m( readData(indx()) ); pPC++; }
AND_indy()710 static void AND_indy()  { AND_m( readData(indy()) ); pPC++; }
AND_zp()711 static void AND_zp()  { AND_m( readData_zp(zp()) ); pPC++; }
AND_zpx()712 static void AND_zpx()  { AND_m( readData_zp(zpx()) ); pPC++; }
713 
714 
ASL_m(ubyte x)715 inline ubyte ASL_m(ubyte x)
716 {
717 	CF = (( x & 128 ) != 0 );
718 	affectNZ( x <<= 1);
719 	return x;
720 }
ASL_AC()721 static void ASL_AC()
722 {
723 	AC = ASL_m(AC);
724 }
ASL_abso()725 static void ASL_abso()
726 {
727 	uword tempAddr = abso();
728 	pPC += 2;
729 	writeData( tempAddr, ASL_m( readData(tempAddr)) );
730 }
ASL_absx()731 static void ASL_absx()
732 {
733 	uword tempAddr = absx();
734 	pPC += 2;
735 	writeData( tempAddr, ASL_m( readData(tempAddr)) );
736 }
ASL_zp()737 static void ASL_zp()
738 {
739 	uword tempAddr = zp();
740 	pPC++;
741 	writeData_zp( tempAddr, ASL_m( readData_zp(tempAddr)) );
742 }
ASL_zpx()743 static void ASL_zpx()
744 {
745 	uword tempAddr = zpx();
746 	pPC++;
747 	writeData_zp( tempAddr, ASL_m( readData_zp(tempAddr)) );
748 }
749 
750 
BCC_()751 static void BCC_()  { branchIfClear(CF); }
752 
BCS_()753 static void BCS_()  { branchIfSet(CF); }
754 
BEQ_()755 static void BEQ_()  { branchIfSet(ZF); }
756 
757 
BIT_m(ubyte x)758 inline void BIT_m(ubyte x)
759 {
760 	ZF = (( AC & x ) == 0 );
761 	VF = (( x & 64 ) != 0 );
762 	NF = (( x & 128 ) != 0 );
763 }
BIT_abso()764 static void BIT_abso()  { BIT_m( readData(abso()) ); pPC += 2; }
BIT_zp()765 static void BIT_zp()  {	BIT_m( readData_zp(zp()) );	pPC++; }
766 
767 
BMI_()768 static void BMI_()  { branchIfSet(NF); }
769 
BNE_()770 static void BNE_()  { branchIfClear(ZF); }
771 
BPL_()772 static void BPL_()  { branchIfClear(NF); }
773 
774 
BRK_()775 static void BRK_()
776 {
777 	BF = (IF = 1);
778 #if !defined(NO_RTS_UPON_BRK)
779 	RTS_();
780 #endif
781 }
782 
783 
BVC_()784 static void BVC_()  { branchIfClear(VF); }
785 
BVS_()786 static void BVS_()  { branchIfSet(VF); }
787 
788 
CLC_()789 static void CLC_()  { CF = 0; }
790 
CLD_()791 static void CLD_()  { DF = 0; }
792 
CLI_()793 static void CLI_()  { IF = 0; }
794 
CLV_()795 static void CLV_()  { VF = 0; }
796 
797 
CMP_m(ubyte x)798 inline void CMP_m(ubyte x)
799 {
800 	ZF = ( AC == x );
801 	CF = ( AC >= x );
802 	NF = ( (sbyte)( AC - x ) < 0 );
803 }
CMP_abso()804 static void CMP_abso()  { CMP_m( readData(abso()) ); pPC += 2; }
CMP_absx()805 static void CMP_absx()  { CMP_m( readData(absx()) ); pPC += 2; }
CMP_absy()806 static void CMP_absy()  { CMP_m( readData(absy()) ); pPC += 2; }
CMP_imm()807 static void CMP_imm()  { CMP_m(imm()); pPC++; }
CMP_indx()808 static void CMP_indx()  { CMP_m( readData(indx()) ); pPC++; }
CMP_indy()809 static void CMP_indy()  { CMP_m( readData(indy()) ); pPC++; }
CMP_zp()810 static void CMP_zp()  { CMP_m( readData_zp(zp()) ); pPC++; }
CMP_zpx()811 static void CMP_zpx()  { CMP_m( readData_zp(zpx()) ); pPC++; }
812 
813 
CPX_m(ubyte x)814 inline void CPX_m(ubyte x)
815 {
816 	ZF = ( XR == x );
817 	CF = ( XR >= x );
818 	NF = ( (sbyte)( XR - x ) < 0 );
819 }
CPX_abso()820 static void CPX_abso()  { CPX_m( readData(abso()) ); pPC += 2; }
CPX_imm()821 static void CPX_imm()  { CPX_m(imm()); pPC++; }
CPX_zp()822 static void CPX_zp()  { CPX_m( readData_zp(zp()) ); pPC++; }
823 
824 
CPY_m(ubyte x)825 inline void CPY_m(ubyte x)
826 {
827 	ZF = ( YR == x );
828 	CF = ( YR >= x );
829 	NF = ( (sbyte)( YR - x ) < 0 );
830 }
CPY_abso()831 static void CPY_abso()  { CPY_m( readData(abso()) ); pPC += 2; }
CPY_imm()832 static void CPY_imm()  { CPY_m(imm()); pPC++; }
CPY_zp()833 static void CPY_zp()  { CPY_m( readData_zp(zp()) ); pPC++; }
834 
835 
DEC_m(uword addr)836 inline void DEC_m(uword addr)
837 {
838 	ubyte x = readData(addr);
839 	affectNZ(--x);
840 	writeData(addr, x);
841 }
DEC_m_zp(uword addr)842 inline void DEC_m_zp(uword addr)
843 {
844 	ubyte x = readData_zp(addr);
845 	affectNZ(--x);
846 	writeData_zp(addr, x);
847 }
DEC_abso()848 static void DEC_abso()  { DEC_m( abso() ); pPC += 2; }
DEC_absx()849 static void DEC_absx()  { DEC_m( absx() ); pPC += 2; }
DEC_zp()850 static void DEC_zp()  { DEC_m_zp( zp() ); pPC++; }
DEC_zpx()851 static void DEC_zpx()  { DEC_m_zp( zpx() ); pPC++; }
852 
853 
DEX_()854 static void DEX_()  { affectNZ(--XR); }
855 
DEY_()856 static void DEY_()  { affectNZ(--YR); }
857 
858 
EOR_m(ubyte x)859 inline void EOR_m(ubyte x)
860 {
861 	AC ^= x;
862 	affectNZ(AC);
863 }
EOR_abso()864 static void EOR_abso()  { EOR_m( readData(abso()) ); pPC += 2; }
EOR_absx()865 static void EOR_absx()  { EOR_m( readData(absx()) ); pPC += 2; }
EOR_absy()866 static void EOR_absy()  { EOR_m( readData(absy()) ); pPC += 2; }
EOR_imm()867 static void EOR_imm()  { EOR_m(imm()); pPC++; }
EOR_indx()868 static void EOR_indx()  { EOR_m( readData(indx()) ); pPC++; }
EOR_indy()869 static void EOR_indy()  { EOR_m( readData(indy()) ); pPC++; }
EOR_zp()870 static void EOR_zp()  { EOR_m( readData_zp(zp()) ); pPC++; }
EOR_zpx()871 static void EOR_zpx()  { EOR_m( readData_zp(zpx()) ); pPC++; }
872 
873 
INC_m(uword addr)874 inline void INC_m(uword addr)
875 {
876 	ubyte x = readData(addr);
877 	affectNZ(++x);
878 	writeData(addr, x);
879 }
INC_m_zp(uword addr)880 inline void INC_m_zp(uword addr)
881 {
882 	ubyte x = readData_zp(addr);
883 	affectNZ(++x);
884 	writeData_zp(addr, x);
885 }
INC_abso()886 static void INC_abso()  { INC_m( abso() ); pPC += 2; }
INC_absx()887 static void INC_absx()  { INC_m( absx() ); pPC += 2; }
INC_zp()888 static void INC_zp()  { INC_m_zp( zp() ); pPC++; }
INC_zpx()889 static void INC_zpx()  { INC_m_zp( zpx() ); pPC++; }
890 
891 
INX_()892 static void INX_()  { affectNZ(++XR); }
893 
INY_()894 static void INY_()  { affectNZ(++YR); }
895 
896 
897 
JMP_()898 static void JMP_()
899 {
900 	PC = abso();
901 	pPC = pPCbase+PC;
902 	evalBankJump();
903 }
904 
JMP_transp()905 static void JMP_transp()
906 {
907 	PC = abso();
908 	if ( (PC>=0xd000) && isKernal )
909 	{
910 		RTS_();  // will set pPC
911 	}
912 	else
913 	{
914 		pPC = pPCbase+PC;
915 	}
916 }
917 
JMP_plain()918 static void JMP_plain()
919 {
920 	PC = abso();
921 	pPC = pPCbase+PC;
922 }
923 
924 
JMP_vec()925 static void JMP_vec()
926 {
927 	uword tempAddrLo = abso();
928 	uword tempAddrHi = (tempAddrLo&0xFF00) | ((tempAddrLo+1)&0x00FF);
929 	PC = readEndian(readData(tempAddrHi),readData(tempAddrLo));
930 	pPC = pPCbase+PC;
931 	evalBankJump();
932 }
933 
JMP_vec_transp()934 static void JMP_vec_transp()
935 {
936 	uword tempAddrLo = abso();
937 	uword tempAddrHi = (tempAddrLo&0xFF00) | ((tempAddrLo+1)&0x00FF);
938 	PC = readEndian(readData(tempAddrHi),readData(tempAddrLo));
939 	if ( (PC>=0xd000) && isKernal )
940 	{
941 		RTS_();  // will set pPC
942 	}
943 	else
944 	{
945 		pPC = pPCbase+PC;
946 	}
947 }
948 
JMP_vec_plain()949 static void JMP_vec_plain()
950 {
951 	uword tempAddrLo = abso();
952 	uword tempAddrHi = (tempAddrLo&0xFF00) | ((tempAddrLo+1)&0x00FF);
953 	PC = readEndian(readData(tempAddrHi),readData(tempAddrLo));
954 	pPC = pPCbase+PC;
955 }
956 
957 
JSR_main()958 inline void JSR_main()
959 {
960 	uword tempPC = abso();
961 	pPC += 2;
962 	PC = pPC-pPCbase;
963 	PC--;
964 	SP--;
965 	writeLEword(c64mem1+SP,PC);
966 	SP--;
967 	checkSP();
968 	PC = tempPC;
969 }
970 
JSR_()971 static void JSR_()
972 {
973 	JSR_main();
974 	pPC = pPCbase+PC;
975 	evalBankJump();
976 }
977 
JSR_transp()978 static void JSR_transp()
979 {
980 	JSR_main();
981 	if ( (PC>=0xd000) && isKernal )
982 	{
983 		RTS_();  // will set pPC
984 	}
985 	else
986 	{
987 		pPC = pPCbase+PC;
988 	}
989 }
990 
JSR_plain()991 static void JSR_plain()
992 {
993 	JSR_main();
994 	pPC = pPCbase+PC;
995 }
996 
997 
LDA_abso()998 static void LDA_abso()  { affectNZ( AC = readData(abso()) ); pPC += 2; }
LDA_absx()999 static void LDA_absx()  { affectNZ( AC = readData( absx() )); pPC += 2; }
LDA_absy()1000 static void LDA_absy()  { affectNZ( AC = readData( absy() ) ); pPC += 2; }
LDA_imm()1001 static void LDA_imm()  { affectNZ( AC = imm() ); pPC++; }
LDA_indx()1002 static void LDA_indx()  { affectNZ( AC = readData( indx() ) ); pPC++; }
LDA_indy()1003 static void LDA_indy()  { affectNZ( AC = readData( indy() ) ); pPC++; }
LDA_zp()1004 static void LDA_zp()  { affectNZ( AC = readData_zp( zp() ) ); pPC++; }
LDA_zpx()1005 static void LDA_zpx()  { affectNZ( AC = readData_zp( zpx() ) ); pPC++; }
1006 
1007 
LDX_abso()1008 static void LDX_abso()  { affectNZ(XR=readData(abso())); pPC += 2; }
LDX_absy()1009 static void LDX_absy()  { affectNZ(XR=readData(absy())); pPC += 2; }
LDX_imm()1010 static void LDX_imm()  { affectNZ(XR=imm()); pPC++; }
LDX_zp()1011 static void LDX_zp()  { affectNZ(XR=readData_zp(zp())); pPC++; }
LDX_zpy()1012 static void LDX_zpy()  { affectNZ(XR=readData_zp(zpy())); pPC++; }
1013 
1014 
LDY_abso()1015 static void LDY_abso()  { affectNZ(YR=readData(abso())); pPC += 2; }
LDY_absx()1016 static void LDY_absx()  { affectNZ(YR=readData(absx())); pPC += 2; }
LDY_imm()1017 static void LDY_imm()  { affectNZ(YR=imm()); pPC++; }
LDY_zp()1018 static void LDY_zp()  { affectNZ(YR=readData_zp(zp())); pPC++; }
LDY_zpx()1019 static void LDY_zpx()  { affectNZ(YR=readData_zp(zpx())); pPC++; }
1020 
1021 
LSR_m(ubyte x)1022 inline ubyte LSR_m(ubyte x)
1023 {
1024 	CF = x & 1;
1025 	x >>= 1;
1026 	NF = 0;
1027 	ZF = (x == 0);
1028 	return x;
1029 }
LSR_AC()1030 static void LSR_AC()
1031 {
1032 	AC = LSR_m(AC);
1033 }
LSR_abso()1034 static void LSR_abso()
1035 {
1036 	uword tempAddr = abso();
1037 	pPC += 2;
1038 	writeData( tempAddr, (LSR_m( readData(tempAddr))) );
1039 }
LSR_absx()1040 static void LSR_absx()
1041 {
1042 	uword tempAddr = absx();
1043 	pPC += 2;
1044 	writeData( tempAddr, (LSR_m( readData(tempAddr))) );
1045 }
LSR_zp()1046 static void LSR_zp()
1047 {
1048 	uword tempAddr = zp();
1049 	pPC++;
1050 	writeData_zp( tempAddr, (LSR_m( readData_zp(tempAddr))) );
1051 }
LSR_zpx()1052 static void LSR_zpx()
1053 {
1054 	uword tempAddr = zpx();
1055 	pPC++;
1056 	writeData_zp( tempAddr, (LSR_m( readData_zp(tempAddr))) );
1057 }
1058 
1059 
ORA_m(ubyte x)1060 inline void ORA_m(ubyte x)
1061 {
1062 	affectNZ( AC |= x );
1063 }
ORA_abso()1064 static void ORA_abso()  { ORA_m( readData(abso()) ); pPC += 2; }
ORA_absx()1065 static void ORA_absx()  { ORA_m( readData(absx()) ); pPC += 2; }
ORA_absy()1066 static void ORA_absy()  { ORA_m( readData(absy()) ); pPC += 2; }
ORA_imm()1067 static void ORA_imm()  { ORA_m(imm()); pPC++; }
ORA_indx()1068 static void ORA_indx()  { ORA_m( readData(indx()) ); pPC++; }
ORA_indy()1069 static void ORA_indy()  { ORA_m( readData(indy()) ); pPC++; }
ORA_zp()1070 static void ORA_zp()  { ORA_m( readData_zp(zp()) ); pPC++; }
ORA_zpx()1071 static void ORA_zpx()  { ORA_m( readData_zp(zpx()) ); pPC++; }
1072 
1073 
NOP_()1074 static void NOP_()  { }
1075 
PHA_()1076 static void PHA_()  { c64mem1[SP--] = AC; }
1077 
1078 
PHP_()1079 static void PHP_()
1080 {
1081 	c64mem1[SP--] = codeSR();
1082 }
1083 
1084 
PLA_()1085 static void PLA_()
1086 {
1087 	affectNZ(AC=c64mem1[++SP]);
1088 }
1089 
1090 
PLP_()1091 static void PLP_()
1092 {
1093 	decodeSR(c64mem1[++SP]);
1094 }
1095 
ROL_m(ubyte x)1096 inline ubyte ROL_m(ubyte x)
1097 {
1098 	ubyte y = ( x << 1 ) + CF;
1099 	CF = (( x & 0x80 ) != 0 );
1100 	affectNZ(y);
1101 	return y;
1102 }
ROL_AC()1103 static void ROL_AC()  { AC=ROL_m(AC); }
ROL_abso()1104 static void ROL_abso()
1105 {
1106 	uword tempAddr = abso();
1107 	pPC += 2;
1108 	writeData( tempAddr, ROL_m( readData(tempAddr)) );
1109 }
ROL_absx()1110 static void ROL_absx()
1111 {
1112 	uword tempAddr = absx();
1113 	pPC += 2;
1114 	writeData( tempAddr, ROL_m( readData(tempAddr)) );
1115 }
ROL_zp()1116 static void ROL_zp()
1117 {
1118 	uword tempAddr = zp();
1119 	pPC++;
1120 	writeData_zp( tempAddr, ROL_m( readData_zp(tempAddr)) );
1121 }
ROL_zpx()1122 static void ROL_zpx()
1123 {
1124 	uword tempAddr = zpx();
1125 	pPC++;
1126 	writeData_zp( tempAddr, ROL_m( readData_zp(tempAddr)) );
1127 }
1128 
ROR_m(ubyte x)1129 inline ubyte ROR_m(ubyte x)
1130 {
1131 	ubyte y = ( x >> 1 ) | ( CF << 7 );
1132 	CF = ( x & 1 );
1133 	affectNZ(y);
1134 	return y;
1135 }
ROR_AC()1136 static void ROR_AC()
1137 {
1138 	AC = ROR_m(AC);
1139 }
ROR_abso()1140 static void ROR_abso()
1141 {
1142 	uword tempAddr = abso();
1143 	pPC += 2;
1144 	writeData( tempAddr, ROR_m( readData(tempAddr)) );
1145 }
ROR_absx()1146 static void ROR_absx()
1147 {
1148 	uword tempAddr = absx();
1149 	pPC += 2;
1150 	writeData( tempAddr, ROR_m( readData(tempAddr)) );
1151 }
ROR_zp()1152 static void ROR_zp()
1153 {
1154 	uword tempAddr = zp();
1155 	pPC++;
1156 	writeData_zp( tempAddr, ROR_m( readData_zp(tempAddr)) );
1157 }
ROR_zpx()1158 static void ROR_zpx()
1159 {
1160 	uword tempAddr = zpx();
1161 	pPC++;
1162 	writeData_zp( tempAddr, ROR_m( readData_zp(tempAddr)) );
1163 }
1164 
1165 
RTI_()1166 static void RTI_()
1167 {
1168 	// equal to RTS_();
1169 	SP++;
1170 	PC =readEndian( c64mem1[SP +1], c64mem1[SP] ) +1;
1171 	pPC = pPCbase+PC;
1172 	SP++;
1173 	checkSP();
1174 }
1175 
1176 
1177 // RTS_() is inline.
1178 
1179 
SBC_m(ubyte s)1180 inline void SBC_m(ubyte s)
1181 {
1182 	s = (~s) & 255;
1183 	if ( DF == 1 )
1184 	{
1185 		uword AC2 = AC +s +CF;
1186 		ZF = ( AC2 == 0 );
1187 		if ((( AC & 15 ) + ( s & 15 ) + CF ) > 9 )
1188 		{
1189 			AC2 += 6;
1190 		}
1191 		VF = ((( AC ^ s ^ AC2 ) & 0x80 ) != 0 ) ^ CF;
1192 		NF = (( AC2 & 128 ) != 0 );
1193 		if ( AC2 > 0x99 )
1194 		{
1195 			AC2 += 96;
1196 		}
1197 		CF = ( AC2 > 0x99 );
1198 		AC = ( AC2 & 255 );
1199 	}
1200 	else
1201 	{
1202 		uword AC2 = AC + s + CF;
1203 		CF = ( AC2 > 255 );
1204 		VF = ((( AC ^ s ^ AC2 ) & 0x80 ) != 0 ) ^ CF;
1205 		affectNZ( AC = ( AC2 & 255 ));
1206 	}
1207 }
SBC_abso()1208 static void SBC_abso()  { SBC_m( readData(abso()) ); pPC += 2; }
SBC_absx()1209 static void SBC_absx()  { SBC_m( readData(absx()) ); pPC += 2; }
SBC_absy()1210 static void SBC_absy()  { SBC_m( readData(absy()) ); pPC += 2; }
SBC_imm()1211 static void SBC_imm()  { SBC_m(imm()); pPC++; }
SBC_indx()1212 static void SBC_indx()  { SBC_m( readData( indx()) ); pPC++; }
SBC_indy()1213 static void SBC_indy()  { SBC_m( readData(indy()) ); pPC++; }
SBC_zp()1214 static void SBC_zp()  { SBC_m( readData_zp(zp()) ); pPC++; }
SBC_zpx()1215 static void SBC_zpx()  { SBC_m( readData_zp(zpx()) ); pPC++; }
1216 
1217 
SEC_()1218 static void SEC_()  { CF=1; }
1219 
SED_()1220 static void SED_()  { DF=1; }
1221 
SEI_()1222 static void SEI_()  { IF=1; }
1223 
1224 
STA_abso()1225 static void STA_abso()  { writeData( abso(), AC ); pPC += 2; }
STA_absx()1226 static void STA_absx()  { writeData( absx(), AC ); pPC += 2; }
STA_absy()1227 static void STA_absy()  { writeData( absy(), AC ); pPC += 2; }
STA_indx()1228 static void STA_indx()  { writeData( indx(), AC ); pPC++; }
STA_indy()1229 static void STA_indy()  { writeData( indy(), AC ); pPC++; }
STA_zp()1230 static void STA_zp()  { writeData_zp( zp(), AC ); pPC++; }
STA_zpx()1231 static void STA_zpx() { writeData_zp( zpx(), AC ); pPC++; }
1232 
1233 
STX_abso()1234 static void STX_abso()  { writeData( abso(), XR ); pPC += 2; }
STX_zp()1235 static void STX_zp()  { writeData_zp( zp(), XR ); pPC++; }
STX_zpy()1236 static void STX_zpy()  { writeData_zp( zpy(), XR ); pPC++; }
1237 
1238 
STY_abso()1239 static void STY_abso()  { writeData( abso(), YR ); pPC += 2; }
STY_zp()1240 static void STY_zp()  { writeData_zp( zp(), YR ); pPC++; }
STY_zpx()1241 static void STY_zpx()  { writeData_zp( zpx(), YR ); pPC++; }
1242 
1243 
TAX_()1244 static void TAX_()  { affectNZ(XR=AC); }
1245 
TAY_()1246 static void TAY_()  { affectNZ(YR=AC); }
1247 
1248 
TSX_()1249 static void TSX_()
1250 {
1251 	XR = SP & 255;
1252 	affectNZ(XR);
1253 }
1254 
TXA_()1255 static void TXA_()  { affectNZ(AC=XR); }
1256 
TXS_()1257 static void TXS_()  { SP = XR | 0x100; checkSP(); }
1258 
TYA_()1259 static void TYA_()  { affectNZ(AC=YR); }
1260 
1261 
1262 // --------------------------------------------------------------------------
1263 // Illegal codes/instructions part (1).
1264 
ILL_TILT()1265 static void ILL_TILT()  { }
1266 
ILL_1NOP()1267 static void ILL_1NOP()  { }
1268 
ILL_2NOP()1269 static void ILL_2NOP()  { pPC++; }
1270 
ILL_3NOP()1271 static void ILL_3NOP()  { pPC += 2; }
1272 
1273 
1274 // --------------------------------------------------------------------------
1275 // Illegal codes/instructions part (2).
1276 
ASLORA_m(uword addr)1277 inline void ASLORA_m(uword addr)
1278 {
1279 	ubyte x = ASL_m(readData(addr));
1280 	writeData(addr,x);
1281 	ORA_m(x);
1282 }
ASLORA_m_zp(uword addr)1283 inline void ASLORA_m_zp(uword addr)
1284 {
1285 	ubyte x = ASL_m(readData_zp(addr));
1286 	writeData_zp(addr,x);
1287 	ORA_m(x);
1288 }
ASLORA_abso()1289 static void ASLORA_abso()
1290 {
1291 	ASLORA_m(abso());
1292 	pPC += 2;
1293 }
ASLORA_absx()1294 static void ASLORA_absx()
1295 {
1296 	ASLORA_m(absx());
1297 	pPC += 2;
1298 }
ASLORA_absy()1299 static void ASLORA_absy()
1300 {
1301 	ASLORA_m(absy());
1302 	pPC += 2;
1303 }
ASLORA_indx()1304 static void ASLORA_indx()
1305 {
1306 	ASLORA_m(indx());
1307 	pPC++;
1308 }
ASLORA_indy()1309 static void ASLORA_indy()
1310 {
1311 	ASLORA_m(indy());
1312 	pPC++;
1313 }
ASLORA_zp()1314 static void ASLORA_zp()
1315 {
1316 	ASLORA_m_zp(zp());
1317 	pPC++;
1318 }
ASLORA_zpx()1319 static void ASLORA_zpx()
1320 {
1321 	ASLORA_m_zp(zpx());
1322 	pPC++;
1323 }
1324 
1325 
ROLAND_m(uword addr)1326 inline void ROLAND_m(uword addr)
1327 {
1328 	uword x = ROL_m(readData(addr));
1329 	writeData(addr,x);
1330 	AND_m(x);
1331 }
ROLAND_m_zp(uword addr)1332 inline void ROLAND_m_zp(uword addr)
1333 {
1334 	uword x = ROL_m(readData_zp(addr));
1335 	writeData_zp(addr,x);
1336 	AND_m(x);
1337 }
ROLAND_abso()1338 static void ROLAND_abso()
1339 {
1340 	ROLAND_m(abso());
1341 	pPC += 2;
1342 }
ROLAND_absx()1343 static void ROLAND_absx()
1344 {
1345 	ROLAND_m(absx());
1346 	pPC += 2;
1347 }
ROLAND_absy()1348 static void ROLAND_absy()
1349 {
1350 	ROLAND_m(absy());
1351 	pPC += 2;
1352 }
ROLAND_indx()1353 static void ROLAND_indx()
1354 {
1355 	ROLAND_m(indx());
1356 	pPC++;
1357 }
ROLAND_indy()1358 static void ROLAND_indy()
1359 {
1360 	ROLAND_m(indy());
1361 	pPC++;
1362 }
ROLAND_zp()1363 static void ROLAND_zp()
1364 {
1365 	ROLAND_m_zp(zp());
1366 	pPC++;
1367 }
ROLAND_zpx()1368 static void ROLAND_zpx()
1369 {
1370 	ROLAND_m_zp(zpx());
1371 	pPC++;
1372 }
1373 
1374 
LSREOR_m(uword addr)1375 inline void LSREOR_m(uword addr)
1376 {
1377 	uword x = LSR_m(readData(addr));
1378 	writeData(addr,x);
1379 	EOR_m(x);
1380 }
LSREOR_m_zp(uword addr)1381 inline void LSREOR_m_zp(uword addr)
1382 {
1383 	uword x = LSR_m(readData_zp(addr));
1384 	writeData_zp(addr,x);
1385 	EOR_m(x);
1386 }
LSREOR_abso()1387 static void LSREOR_abso()
1388 {
1389 	LSREOR_m(abso());
1390 	pPC += 2;
1391 }
LSREOR_absx()1392 static void LSREOR_absx()
1393 {
1394 	LSREOR_m(absx());
1395 	pPC += 2;
1396 }
LSREOR_absy()1397 static void LSREOR_absy()
1398 {
1399 	LSREOR_m(absy());
1400 	pPC += 2;
1401 }
LSREOR_indx()1402 static void LSREOR_indx()
1403 {
1404 	LSREOR_m(indx());
1405 	pPC++;
1406 }
LSREOR_indy()1407 static void LSREOR_indy()
1408 {
1409 	LSREOR_m(indy());
1410 	pPC++;
1411 }
LSREOR_zp()1412 static void LSREOR_zp()
1413 {
1414 	LSREOR_m_zp(zp());
1415 	pPC++;
1416 }
LSREOR_zpx()1417 static void LSREOR_zpx()
1418 {
1419 	LSREOR_m_zp(zpx());
1420 	pPC++;
1421 }
1422 
1423 
RORADC_m(uword addr)1424 inline void RORADC_m(uword addr)
1425 {
1426 	ubyte x = ROR_m(readData(addr));
1427 	writeData(addr,x);
1428 	ADC_m(x);
1429 }
RORADC_m_zp(uword addr)1430 inline void RORADC_m_zp(uword addr)
1431 {
1432 	ubyte x = ROR_m(readData_zp(addr));
1433 	writeData_zp(addr,x);
1434 	ADC_m(x);
1435 }
RORADC_abso()1436 static void RORADC_abso()
1437 {
1438 	RORADC_m(abso());
1439 	pPC += 2;
1440 }
RORADC_absx()1441 static void RORADC_absx()
1442 {
1443 	RORADC_m(absx());
1444 	pPC += 2;
1445 }
RORADC_absy()1446 static void RORADC_absy()
1447 {
1448 	RORADC_m(absy());
1449 	pPC += 2;
1450 }
RORADC_indx()1451 static void RORADC_indx()
1452 {
1453 	RORADC_m(indx());
1454 	pPC++;
1455 }
RORADC_indy()1456 static void RORADC_indy()
1457 {
1458 	RORADC_m(indy());
1459 	pPC++;
1460 }
RORADC_zp()1461 static void RORADC_zp()
1462 {
1463 	RORADC_m_zp(zp());
1464 	pPC++;
1465 }
RORADC_zpx()1466 static void RORADC_zpx()
1467 {
1468 	RORADC_m_zp(zpx());
1469 	pPC++;
1470 }
1471 
1472 
DECCMP_m(uword addr)1473 inline void DECCMP_m(uword addr)
1474 {
1475 	ubyte x = readData(addr);
1476 	writeData(addr,(--x));
1477 	CMP_m(x);
1478 }
DECCMP_m_zp(uword addr)1479 inline void DECCMP_m_zp(uword addr)
1480 {
1481 	ubyte x = readData_zp(addr);
1482 	writeData_zp(addr,(--x));
1483 	CMP_m(x);
1484 }
DECCMP_abso()1485 static void DECCMP_abso()
1486 {
1487 	DECCMP_m(abso());
1488 	pPC += 2;
1489 }
DECCMP_absx()1490 static void DECCMP_absx()
1491 {
1492 	DECCMP_m(absx());
1493 	pPC += 2;
1494 }
DECCMP_absy()1495 static void DECCMP_absy()
1496 {
1497 	DECCMP_m(absy());
1498 	pPC += 2;
1499 }
DECCMP_indx()1500 static void DECCMP_indx()
1501 {
1502 	DECCMP_m(indx());
1503 	pPC++;
1504 }
DECCMP_indy()1505 static void DECCMP_indy()
1506 {
1507 	DECCMP_m(indy());
1508 	pPC++;
1509 }
DECCMP_zp()1510 static void DECCMP_zp()
1511 {
1512 	DECCMP_m_zp(zp());
1513 	pPC++;
1514 }
DECCMP_zpx()1515 static void DECCMP_zpx()
1516 {
1517 	DECCMP_m_zp(zpx());
1518 	pPC++;
1519 }
1520 
1521 
INCSBC_m(uword addr)1522 inline void INCSBC_m(uword addr)
1523 {
1524 	ubyte x = readData(addr);
1525 	writeData(addr,(++x));
1526 	SBC_m(x);
1527 }
INCSBC_m_zp(uword addr)1528 inline void INCSBC_m_zp(uword addr)
1529 {
1530 	ubyte x = readData_zp(addr);
1531 	writeData_zp(addr,(++x));
1532 	SBC_m(x);
1533 }
INCSBC_abso()1534 static void INCSBC_abso()
1535 {
1536 	INCSBC_m(abso());
1537 	pPC += 2;
1538 }
INCSBC_absx()1539 static void INCSBC_absx()
1540 {
1541 	INCSBC_m(absx());
1542 	pPC += 2;
1543 }
INCSBC_absy()1544 static void INCSBC_absy()
1545 {
1546 	INCSBC_m(absy());
1547 	pPC += 2;
1548 }
INCSBC_indx()1549 static void INCSBC_indx()
1550 {
1551 	INCSBC_m(indx());
1552 	pPC++;
1553 }
INCSBC_indy()1554 static void INCSBC_indy()
1555 {
1556 	INCSBC_m(indy());
1557 	pPC++;
1558 }
INCSBC_zp()1559 static void INCSBC_zp()
1560 {
1561 	INCSBC_m_zp(zp());
1562 	pPC++;
1563 }
INCSBC_zpx()1564 static void INCSBC_zpx()
1565 {
1566 	INCSBC_m_zp(zpx());
1567 	pPC++;
1568 }
1569 
1570 
1571 // --------------------------------------------------------------------------
1572 // Illegal codes/instructions part (3). This implementation is considered to
1573 // be only partially working due to inconsistencies in the available
1574 // documentation.
1575 // Note: In some of the functions emulated, defined instructions are used and
1576 // already increment the PC ! Take care, and do not increment further !
1577 // Double-setting of processor flags can occur, too.
1578 
ILL_0B()1579 static void ILL_0B() // equal to 2B
1580 {
1581 	AND_imm();
1582 	CF = NF;
1583 }
1584 
ILL_4B()1585 static void ILL_4B()
1586 {
1587 	AND_imm();
1588 	LSR_AC();
1589 }
1590 
ILL_6B()1591 static void ILL_6B()
1592 {
1593 	if (DF == 0)
1594 	{
1595 		AND_imm();
1596 		ROR_AC();
1597 		CF = (AC & 1);
1598 		VF = (AC >> 5) ^ (AC >> 6);
1599 	}
1600 }
1601 
ILL_83()1602 static void ILL_83()
1603 {
1604 	writeData(indx(),AC & XR);
1605 	pPC++;
1606 }
1607 
ILL_87()1608 static void ILL_87()
1609 {
1610 	writeData_zp(zp(),AC & XR);
1611 	pPC++;
1612 }
1613 
ILL_8B()1614 static void ILL_8B()
1615 {
1616 	TXA_();
1617 	AND_imm();
1618 }
1619 
ILL_8F()1620 static void ILL_8F()
1621 {
1622 	writeData(abso(),AC & XR);
1623 	pPC += 2;
1624 }
1625 
ILL_93()1626 static void ILL_93()
1627 {
1628 	writeData(indy(), AC & XR & (1+(readData((*pPC)+1) & 0xFF)));
1629 	pPC++;
1630 }
1631 
ILL_97()1632 static void ILL_97()
1633 {
1634 	writeData_zp(zpx(),AC & XR);
1635 	pPC++;
1636 }
1637 
ILL_9B()1638 static void ILL_9B()
1639 {
1640 	SP = 0x100 | (AC & XR);
1641 	writeData(absy(),(SP & ((*pPC+1)+1)));
1642 	pPC += 2;
1643 	checkSP();
1644 }
1645 
ILL_9C()1646 static void ILL_9C()
1647 {
1648 	writeData(absx(),(YR & ((*pPC+1)+1)));
1649 	pPC += 2;
1650 }
1651 
ILL_9E()1652 static void ILL_9E()
1653 {
1654 	writeData(absy(),(XR & ((*pPC+1)+1)));
1655 	pPC += 2;
1656 }
1657 
ILL_9F()1658 static void ILL_9F()
1659 {
1660 	writeData(absy(),(AC & XR & ((*pPC+1)+1)));
1661 	pPC += 2;
1662 }
1663 
ILL_A3()1664 static void ILL_A3()
1665 {
1666 	LDA_indx();
1667 	TAX_();
1668 }
1669 
ILL_A7()1670 static void ILL_A7()
1671 {
1672 	LDA_zp();
1673 	TAX_();
1674 }
1675 
ILL_AB()1676 static void ILL_AB()
1677 // Taken from VICE because a single music player has been found
1678 // (not in HVSC) which seems to need ILL_AB implemented like this
1679 // (or similarly) in order to work.
1680 {
1681     AC = XR = ((AC|0xee)&(*pPC++));
1682     affectNZ( AC );
1683 }
1684 
ILL_AF()1685 static void ILL_AF()
1686 {
1687 	LDA_abso();
1688 	TAX_();
1689 }
1690 
ILL_B3()1691 static void ILL_B3()
1692 {
1693 	LDA_indy();
1694 	TAX_();
1695 }
1696 
ILL_B7()1697 static void ILL_B7()
1698 {
1699 	affectNZ(AC = readData_zp(zpy()));  // would be LDA_zpy()
1700 	TAX_();
1701 	pPC++;
1702 }
1703 
ILL_BB()1704 static void ILL_BB()
1705 {
1706 	XR = (SP & absy());
1707 	pPC += 2;
1708 	TXS_();
1709 	TXA_();
1710 }
1711 
ILL_BF()1712 static void ILL_BF()
1713 {
1714 	LDA_absy();
1715 	TAX_();
1716 }
1717 
ILL_CB()1718 static void ILL_CB()
1719 {
1720 	uword tmp = XR & AC;
1721 	tmp -= imm();
1722 	CF = (tmp > 255);
1723 	affectNZ(XR=(tmp&255));
1724 }
1725 
ILL_EB()1726 static void ILL_EB()
1727 {
1728 	SBC_imm();
1729 }
1730 
1731 // --------------------------------------------------------------------------
1732 
1733 static ptr2func instrList[] =
1734 {
1735 	&BRK_, &ORA_indx, &ILL_TILT, &ASLORA_indx, &ILL_2NOP, &ORA_zp, &ASL_zp, &ASLORA_zp,
1736 	&PHP_, &ORA_imm, &ASL_AC, &ILL_0B, &ILL_3NOP, &ORA_abso, &ASL_abso, &ASLORA_abso,
1737 	&BPL_, &ORA_indy, &ILL_TILT, &ASLORA_indy, &ILL_2NOP, &ORA_zpx, &ASL_zpx, &ASLORA_zpx,
1738 	&CLC_, &ORA_absy, &ILL_1NOP, &ASLORA_absy, &ILL_3NOP, &ORA_absx, &ASL_absx, &ASLORA_absx,
1739 	&JSR_, &AND_indx, &ILL_TILT, &ROLAND_indx, &BIT_zp, &AND_zp, &ROL_zp, &ROLAND_zp,
1740 	&PLP_, &AND_imm, &ROL_AC, &ILL_0B, &BIT_abso, &AND_abso, &ROL_abso, &ROLAND_abso,
1741 	&BMI_, &AND_indy, &ILL_TILT, &ROLAND_indy, &ILL_2NOP, &AND_zpx, &ROL_zpx, &ROLAND_zpx,
1742 	&SEC_, &AND_absy, &ILL_1NOP, &ROLAND_absy, &ILL_3NOP, &AND_absx, &ROL_absx, &ROLAND_absx,
1743 	// 0x40
1744 	&RTI_, &EOR_indx, &ILL_TILT, &LSREOR_indx, &ILL_2NOP, &EOR_zp, &LSR_zp, &LSREOR_zp,
1745 	&PHA_, &EOR_imm, &LSR_AC, &ILL_4B, &JMP_, &EOR_abso, &LSR_abso, &LSREOR_abso,
1746 	&BVC_, &EOR_indy, &ILL_TILT, &LSREOR_indy, &ILL_2NOP, &EOR_zpx, &LSR_zpx, &LSREOR_zpx,
1747 	&CLI_, &EOR_absy, &ILL_1NOP, &LSREOR_absy, &ILL_3NOP, &EOR_absx, &LSR_absx, &LSREOR_absx,
1748 	&RTS_, &ADC_indx, &ILL_TILT, &RORADC_indx, &ILL_2NOP, &ADC_zp, &ROR_zp, &RORADC_zp,
1749 	&PLA_, &ADC_imm, &ROR_AC, &ILL_6B, &JMP_vec, &ADC_abso, &ROR_abso, &RORADC_abso,
1750 	&BVS_, &ADC_indy, &ILL_TILT, &RORADC_indy, &ILL_2NOP, &ADC_zpx, &ROR_zpx, &RORADC_zpx,
1751 	&SEI_, &ADC_absy, &ILL_1NOP, &RORADC_absy, &ILL_3NOP, &ADC_absx, &ROR_absx, &RORADC_absx,
1752 	// 0x80
1753 	&ILL_2NOP, &STA_indx, &ILL_2NOP, &ILL_83, &STY_zp, &STA_zp, &STX_zp, &ILL_87,
1754 	&DEY_, &ILL_2NOP, &TXA_, &ILL_8B, &STY_abso, &STA_abso, &STX_abso, &ILL_8F,
1755 	&BCC_, &STA_indy, &ILL_TILT, &ILL_93, &STY_zpx, &STA_zpx, &STX_zpy, &ILL_97,
1756 	&TYA_, &STA_absy, &TXS_, &ILL_9B, &ILL_9C, &STA_absx, &ILL_9E, &ILL_9F,
1757 	&LDY_imm, &LDA_indx, &LDX_imm, &ILL_A3, &LDY_zp, &LDA_zp, &LDX_zp, &ILL_A7,
1758 	&TAY_, &LDA_imm, &TAX_, &ILL_AB, &LDY_abso, &LDA_abso, &LDX_abso, &ILL_AF,
1759 	&BCS_, &LDA_indy, &ILL_TILT, &ILL_B3, &LDY_zpx, &LDA_zpx, &LDX_zpy, &ILL_B7,
1760 	&CLV_, &LDA_absy, &TSX_, &ILL_BB, &LDY_absx, &LDA_absx, &LDX_absy, &ILL_BF,
1761 	// 0xC0
1762 	&CPY_imm, &CMP_indx, &ILL_2NOP, &DECCMP_indx, &CPY_zp, &CMP_zp, &DEC_zp, &DECCMP_zp,
1763 	&INY_, &CMP_imm, &DEX_, &ILL_CB, &CPY_abso, &CMP_abso, &DEC_abso, &DECCMP_abso,
1764 	&BNE_, &CMP_indy, &ILL_TILT, &DECCMP_indy, &ILL_2NOP, &CMP_zpx, &DEC_zpx, &DECCMP_zpx,
1765 	&CLD_, &CMP_absy, &ILL_1NOP, &DECCMP_absy, &ILL_3NOP, &CMP_absx, &DEC_absx, &DECCMP_absx,
1766 	&CPX_imm, &SBC_indx, &ILL_2NOP, &INCSBC_indx, &CPX_zp, &SBC_zp, &INC_zp, &INCSBC_zp,
1767 	&INX_, &SBC_imm,  &NOP_, &ILL_EB, &CPX_abso, &SBC_abso, &INC_abso, &INCSBC_abso,
1768 	&BEQ_, &SBC_indy, &ILL_TILT, &INCSBC_indy, &ILL_2NOP, &SBC_zpx, &INC_zpx, &INCSBC_zpx,
1769 	&SED_, &SBC_absy, &ILL_1NOP, &INCSBC_absy, &ILL_3NOP, &SBC_absx, &INC_absx, &INCSBC_absx
1770 };
1771 
1772 
1773 static int memoryMode = MPU_TRANSPARENT_ROM;  // the default
1774 
1775 
initInterpreter(int inMemoryMode)1776 void initInterpreter(int inMemoryMode)
1777 {
1778 	memoryMode = inMemoryMode;
1779 	if (memoryMode == MPU_TRANSPARENT_ROM)
1780 	{
1781 		readData = &readData_transp;
1782 		writeData = &writeData_bs;
1783 		instrList[0x20] = &JSR_transp;
1784 		instrList[0x4C] = &JMP_transp;
1785 		instrList[0x6C] = &JMP_vec_transp;
1786 		// Make the memory buffers accessible to the whole emulator engine.
1787 		// Use two distinct 64KB memory areas.
1788 		c64mem1 = c64ramBuf;
1789 		c64mem2 = c64romBuf;
1790 	}
1791 	else if (memoryMode == MPU_PLAYSID_ENVIRONMENT)
1792 	{
1793 		readData = &readData_plain;
1794 		writeData = &writeData_plain;
1795 		instrList[0x20] = &JSR_plain;
1796 		instrList[0x4C] = &JMP_plain;
1797 		instrList[0x6C] = &JMP_vec_plain;
1798 		// Make the memory buffers accessible to the whole emulator engine.
1799 		// Use a single 64KB memory area.
1800 		c64mem2 = (c64mem1 = c64ramBuf);
1801 	}
1802 	else  // if (memoryMode == MPU_BANK_SWITCHING)
1803 	{
1804 		readData = &readData_bs;
1805 		writeData = &writeData_bs;
1806 		instrList[0x20] = &JSR_;
1807 		instrList[0x4C] = &JMP_;
1808 		instrList[0x6C] = &JMP_vec;
1809 		// Make the memory buffers accessible to the whole emulator engine.
1810 		// Use two distinct 64KB memory areas.
1811 		c64mem1 = c64ramBuf;
1812 		c64mem2 = c64romBuf;
1813 	}
1814 	bankSelReg = c64ramBuf+1;  // extra pointer
1815 	// Set code execution segment to RAM.
1816 	pPCbase = c64ramBuf;
1817 	pPCend = c64ramBuf+65536;
1818 }
1819 
1820 
interpreter(uword p,ubyte ramrom,ubyte a,ubyte x,ubyte y)1821 bool interpreter(uword p, ubyte ramrom, ubyte a, ubyte x, ubyte y)
1822 {
1823 	if (memoryMode == MPU_PLAYSID_ENVIRONMENT)
1824 	{
1825 		AC = a;
1826 		XR = 0;
1827 		YR = 0;
1828 	}
1829 	else
1830 	{
1831 		*bankSelReg = ramrom;
1832 		evalBankSelect();
1833 		AC = a;
1834 		XR = x;
1835 		YR = y;
1836 	}
1837 
1838 	// Set program-counter (pointer instead of raw PC).
1839 	pPC = pPCbase+p;
1840 
1841 	resetSP();
1842 	resetSR();
1843 	sidKeysOff[4] = (sidKeysOff[4+7] = (sidKeysOff[4+14] = false));
1844 	sidKeysOn[4] = (sidKeysOn[4+7] = (sidKeysOn[4+14] = false));
1845 
1846 	do
1847 	{
1848 		(*instrList[*(pPC++)])();
1849 	}
1850 	while (stackIsOkay&&(pPC<pPCend));
1851 
1852 	return true;
1853 }
1854 
1855 
c64memReset(int clockSpeed,ubyte randomSeed)1856 void c64memReset(int clockSpeed, ubyte randomSeed)
1857 {
1858 	fakeReadTimer += randomSeed;
1859 
1860 	if ((c64mem1 != 0) && (c64mem2 != 0))
1861 	{
1862 		c64mem1[0] = 0x2F;
1863 		// defaults: Basic-ROM on, Kernal-ROM on, I/O on
1864 		c64mem1[1] = 0x07;
1865 		evalBankSelect();
1866 
1867 		// CIA-Timer A $DC04/5 = $4025 PAL, $4295 NTSC
1868 		if (clockSpeed == SIDTUNE_CLOCK_NTSC)
1869 		{
1870 			c64mem1[0x02a6] = 0;     // NTSC
1871 			c64mem2[0xdc04] = 0x95;
1872 			c64mem2[0xdc05] = 0x42;
1873 		}
1874 		else  // if (clockSpeed == SIDTUNE_CLOCK_PAL)
1875 		{
1876 			c64mem1[0x02a6] = 1;     // PAL
1877 			c64mem2[0xdc04] = 0x25;
1878 			c64mem2[0xdc05] = 0x40;
1879 		}
1880 
1881 		// fake VBI-interrupts that do $D019, BMI ...
1882 		c64mem2[0xd019] = 0xff;
1883 
1884 		// software vectors
1885 		// IRQ to $EA31
1886 		c64mem1[0x0314] = 0x31;
1887 		c64mem1[0x0315] = 0xea;
1888 		// BRK to $FE66
1889 		c64mem1[0x0316] = 0x66;
1890 		c64mem1[0x0317] = 0xfe;
1891 		// NMI to $FE47
1892 		c64mem1[0x0318] = 0x47;
1893 		c64mem1[0x0319] = 0xfe;
1894 
1895 		// hardware vectors
1896 		if (memoryMode == MPU_PLAYSID_ENVIRONMENT)
1897 		{
1898 			c64mem1[0xff48] = 0x6c;
1899 			c64mem1[0xff49] = 0x14;
1900 			c64mem1[0xff4a] = 0x03;
1901 			c64mem1[0xfffa] = 0xf8;
1902 			c64mem1[0xfffb] = 0xff;
1903 			c64mem1[0xfffe] = 0x48;
1904 			c64mem1[0xffff] = 0xff;
1905 		}
1906 		else
1907 		{
1908 			// NMI to $FE43
1909 			c64mem1[0xfffa] = 0x43;
1910 			c64mem1[0xfffb] = 0xfe;
1911 			// RESET to $FCE2
1912 			c64mem1[0xfffc] = 0xe2;
1913 			c64mem1[0xfffd] = 0xfc;
1914 			// IRQ to $FF48
1915 			c64mem1[0xfffe] = 0x48;
1916 			c64mem1[0xffff] = 0xff;
1917 		}
1918 
1919 		// clear SID
1920 		for ( int i = 0; i < 0x1d; i++ )
1921 		{
1922 			c64mem2[0xd400 +i] = 0;
1923 		}
1924 		// default Mastervolume, no filter
1925 		c64mem2[0xd418] = (sidLastValue = 0x0f);
1926 	}
1927 }
1928 
1929 
c64memClear()1930 void c64memClear()
1931 {
1932 	// Clear entire RAM and ROM.
1933 	for ( udword i = 0; i < 0x10000; i++ )
1934 	{
1935 		c64mem1[i] = 0;
1936 		if (memoryMode != MPU_PLAYSID_ENVIRONMENT)
1937 		{
1938 			c64mem2[i] = 0;
1939 		}
1940 		sidLastValue = 0;
1941 	}
1942 	if (memoryMode == MPU_PLAYSID_ENVIRONMENT)
1943 	{
1944 		// Fill Kernal-ROM address space with RTI instructions.
1945 		for ( udword j = 0xE000; j < 0x10000; j++ )
1946 		{
1947 			c64mem1[j] = 0x40;
1948 		}
1949 	}
1950 	else
1951 	{
1952 		// Fill Basic-ROM address space with RTS instructions.
1953 		for ( udword j1 = 0xA000; j1 < 0xC000; j1++ )
1954 		{
1955 			c64mem2[j1] = 0x60;
1956 		}
1957 		// Fill Kernal-ROM address space with RTI instructions.
1958 		for ( udword j2 = 0xE000; j2 < 0x10000; j2++ )
1959 		{
1960 			c64mem2[j2] = 0x40;
1961 		}
1962 	}
1963 }
1964 
1965 
1966 //  Input: A 16-bit effective address
1967 // Output: A default bank-select value for $01.
c64memRamRom(uword address)1968 ubyte c64memRamRom( uword address )
1969 {
1970 	if (memoryMode == MPU_PLAYSID_ENVIRONMENT)
1971 	{
1972 		return 4;  // RAM only, but special I/O mode
1973 	}
1974 	else
1975 	{
1976 		if ( address < 0xa000 )
1977 		{
1978 			return 7;  // Basic-ROM, Kernal-ROM, I/O
1979 		}
1980 		else if ( address < 0xd000 )
1981 		{
1982 			return 6;  // Kernal-ROM, I/O
1983 		}
1984 		else if ( address >= 0xe000 )
1985 		{
1986 			return 5;  // I/O only
1987 		}
1988 		else
1989 		{
1990 			return 4;  // RAM only
1991 		}
1992 	}
1993 }
1994