EOR: Some Special Uses
Posted on
By Kodiak
				
																				
										In my own personal, ongoing quest for doing things quicker or more RAM-efficiently with 6502 assembly on the Commodore 64, some time ago I blundered into some nice little hacks with the 
										EOR instruction, the "Exclusive OR".
										
										Some of my favourites are:
										
									
- A tiny EOR-based switch aka "alternator" for frame-skipping in raster interrupts.
- Using EOR for faster subtraction.
- Using EOR for faster addition.
	
										
										Lets consider each of them in turn:
										
										1. EOR-based alternator: At some point in many 6502 coding scenarios, you will probably want to perform certain tasks only on every other frame; it could be
										some game AI, it could be something like Toggleplexing, an audio effect, a scroll event or whatever; 
										the key thing is that you need to do it every other frame.
										
										For this, you could do as follows (which has probably been used by many coders since the 1980s, so it's not my invention!) inside one interrupt handler, so that it fires once every
										frame (i.e. screen refresh):
										
										LDA ZPTOGGLE
										
 
										EOR #$01
										
										STA ZPTOGGLE
										
										BNE ODDFRAME ; Branch to ODDFRAME every "odd" frame, whereas this BNE is ignored on every "even" frame
										
										; EVENFRAME code goes here
										
										
										All you have to do when setting this up at the start of the program is to ensure the variable ZPTOGGLE = either 0 or 1 and EOR will invert that value every frame, producing a 
										0,1,0,1,0,1,0,1,0 cycle ad infinitum.
										
	
										SPECIAL NOTE: I like to use another way to perform the toggle logic that saves 1 cycle on both odd and even paths compared to the above, but it requires the
										use of self-modifying code 
										and consumes more RAM for the logic... this is scheduled for inclusion in the next Newsletter for subscribers.
										
										
										2. EOR for faster subtraction: Normally you would subtract using SEC
										and SBC, such as per the following example:
										
										LDA #%00011111
										
										SEC								
										
										SBC BITTABLE,Y	; where BITTABLE,Y is known to hold only values less than #%00011111
										
										That takes 2 + 2 + 4* cycles = 8-9 cycles, the actual number depending on whether or not the page boundary is crossed by the SBC,Y operation; and if we say, by way
										of illustration, that the value in BITTABLE,Y = #%00001111 (15 in decimal), the result will be #%00010000, i.e, 31 - 15 = 16.
										
										So if we can safely predict the range of the value being subtracted, we could use EOR to do the subtraction like this:
										
										LDA BITTABLE,Y
										
										EOR #%00011111 ; Shorthand for subtracting BITTABLE,Y from #%00011111
										
										The same calculation (with the same result, obviously!) now takes 4* + 2 cycles = 6-7 cycles, the actual number depending on whether or not the page boundary is 
										crossed by the LDA,Y operation, with the extra bonus of the carry flag remaining unaltered by the calculation!
										
										Again, the idea of using EOR for this kind of subtraction is not my invention and it's probably impossible to know who did it first, but it's slick and saves 2 precious CPU 
										cycles and 1 byte of RAM from the standard way of subtracting.
										
										(Incidentally, this forms part of the landscape damage encoding routine in Parallaxian, in which trees set on fire
										by bombing are still on fire next time they scroll on to the screen).
										
										
										3. EOR for faster addition: Just as you can use EOR for fast subtraction if the constraints of that subtraction are first known and understood, so you can also
										use it for some fast addition, with the same fundamental proviso.
										
										For example, let's say you want to add any number less than #$F0 (in decimal, 128 or, in binary #%10000000) to #$F0; 
										normally, you would use CLC
										and ADC to do the following 
										(we should keep it all in binary to help understand what's happening with the various bits):
										
										LDA #%00001010	
										
										CLC
										
										ADC #%10000000
										
										That gives a result of #%10001010 (138 in decimal) in the A-reg and takes 2 + 2 + 2 = 6 cycles, but consider that the following will give you the same result:
										
										LDA #%00001010	
										
										EOR #%10000000
										
										...which puts #%10001010 (138 in decimal) in the A-reg but takes only 2 + 2 = 4 cycles, with the saving still applying over different addressing modes if you replace 
										like with like and, as with the EOR subtraction, you walk out of the calculation with the carry flag unaffected!
										
										
										Of course, that's only the tip of the iceberg in terms of what can be done with EOR; for example, you can use it to save space in the 
										VIC bank if you have a sprite that has	a flickering flame such as that used by Parallaxian's "Backfire" enemy - the
										flickering flame is highlighted in yellow below:
									
 
									
										So instead of keeping the full definitions for the craft with and without the flame showing, you only need one and use EOR to manually draw / clear the sprite data for the flame
										on alternating frames.
										
										Finally, there are some helpful generic, non-C64-related tools online that will allow you to perform tests using the big 3 logical operators of AND, ORA and EOR (which sometimes
										is known as XOR), such as this one: bitwise-calculator.
										
										Similar post:
										
										Illegal Opcode SAX/AXS: A Practical Use
										
									
									____
									
									If you value my work and want to support me, a small donation via PayPal would be nice (and thanks if you do!) 
									
								
Help Make Parallaxian Happen!
...and get special perks!
	
								Progress on Parallaxian has slowed down since summer 2021 for several reasons, one of which has been the very low level of support from
								the C64 scene which has made it difficult to continue justifying to my family the long hours of hard work a project as complex as this requires.
								
								Now, I understand these are difficult times and I admit I am not entitled to any support at all, but it really does encourage me to continue developing
								this sensational game when you make a regular 
								Paypal donation.
								
								And as a special thank you, all who do this can enjoy the following perks:	
							
- Your name credited in the game (unless you opt out of it if you have the same kind of incognito hermit tendencies I do).
- Access to the ongoing beta-testing of the game (unless you would prefer not to see it before its release date).
- The finished game on media (e.g. cartridge) for FREE one week before its release.