Skip to content →

illegal opcodes

At some point, you will encounter an opcode, that you did not yet implement, despite the fact that you included all the opcodes provided in the C64 wiki.

This opcode will be 0x04, and this will be the sign for you, that you can (probably) emulate every single official opcode to the 6502. But, for completions sake, we are not going to stop there, we are also including the unofficial / illegal opcodes.

A great resource for this can be found here (credits go to Adam Vardy – This list not only lists all the illegal opcodes, it also explains what they do, and very important, also lists the timings.

With further comparison to nestest we can check how our opcodes are working out, if our PPU / CPU cycles are correct and if we are making mistakes at any time.


Most of the opcodes are only a combination of the legal opcodes, so we can just call them in this combination, easy right?

SLO {adr} = ASL {adr} + ORA {adr}
RLA {adr} = ROL {adr} + AND {adr}
SRE {adr} = LSR {adr} + EOR {adr}
RRA {adr} = ROR {adr} + ADC {adr}
SAX {adr} = store A&X into {adr}
LAX {adr} = LDA {adr} + LDX {adr}
DCP {adr} = DEC {adr} + CMP {adr}
ISC {adr} = INC {adr} + SBC {adr} 
uint8_t RLA(uint16_t adr, uint8_t cycles) {
	ROL(adr, cycles);
	AND(adr, cycles);
	return cycles;
uint8_t SRE(uint16_t adr, uint8_t cycles) {
	LSR(adr, cycles);
	EOR(adr, cycles);
	return cycles;
uint8_t RRA(uint16_t adr, uint8_t cycles) {
	ROR(adr, cycles);
	ADC(adr, cycles);
	return cycles;

At one point, our log will pass nestest.log perfectly, and that will be our sign, to go onto the next steps.

1:1 comparison to nestest.log (modified) – my log only tries to continue executing

So, now that we pass nestest.log, at least on paper, it’s time to load up a cartridge, and try to get some graphics working.


Leave a Reply