Printing to the screen was a little too ambitious as the next step. Instead I looked at something arguably more useful; comparison and branching. Since part of what my PREFS program does is unique to the Atari XL/XE series I decided to have it check for those versions of the OS. If they are found, then the XL/XE portion of the code is executed, otherwise it will just exit.
OS Version Detection
There are two memory locations in the Atari which reflect the OS version. It moved by one byte between the original Atari 400/800 OS and the Atari XL/XE OS. The older location is $FFF8 (65528). There are three values representing different revisions and television display standards (North American NTSC and European PAL – although the delineation is not that cut and dry). For this programs purposes I only need to check for the XL/XE so the older location is only being documented.
- 221 = Atari 400/800 OS, Revision A, NTSC
- 214 = Atari 400/800 OS, Revision A, PAL
- 243 = Atari 400/800 OS, Revision B, NTSC
The newer location is one byte lower in memory at $FFF7 (65527). There are several values that it can have. For my purposes I’m only concerned with values 1-4, 10 and 11.
- 1 = Atari XL/XE OS, Revision 1
- 2 = Atari XL/XE OS, Revision 2
- 3 = Atari XL/XE OS, Revision 3
- 4 = Atari XL/XE OS, Revision 4
- 10 = Atari XL/XE OS, Revision 10
- 11 = Atari XL/XE OS, Revision 11
If/then logic in 6502 assembly is implemented with a combination of comparison and branching instructions. There are three comparison instructions: CMP, CPX, CPY. CMP compares values in the accumulator, while CPX and CPY compare values in the X and Y registers respectively.
There are eight branch instructions. I’m only going to cover the ones I use, others will be introduced as I need them. For now, BCC and BEQ are of interest.
- BCC tells the processor to Branch if the Carry flag is Clear.
- BEQ tells the processor to Branch if the values compared are equal, but more precisely if the result of the comparison leaves the zero flag set.
If / Then Construction
The comparison and branching instructions are not very useful by themselves. Coupling them together allows you to build the if/then constructs which make them very useful.
Here are five examples of combining the instructions into useful if/then constructs. The LDA instructions here load a value using Immediate Addressing mode (the specified value) written as “LDA #value”. To load the accumulator with a value from a memory location, you would use the Absolute Addressing mode which is written as “LDA $hhhh”. As you will see later, I use absolute addressing in the updates to my program.
- Accumulator = VALUE2 :
LDA #VALUE1 CMP #VALUE2 BEQ
- Accumulator <> VALUE2 :
LDA #VALUE1 CMP #VALUE2 BNE
- Accumulator >= VALUE2 :
LDA #VALUE1 CMP #VALUE2 BCS
- Accumulator > VALUE2 :
LDA #VALUE1 CMP #VALUE2 BEQ BCS
- Accumulator < VALUE2 :
LDA #VALUE1 CMP #VALUE2 BCC
Putting It To Use
I’ve modified my PREFS program with the appropriate constructs. I’ve added many definitions since last time and renumbered to make room for expansion.
10 *= $3800 20 .OPT OBJ 49 ; Defines 50 RMARG = 82 51 CFORE = 709 52 CBACK = 710 53 KDELY = 729 54 KRATE = 730 55 CLICK = 731 60 OSNEW = $FFF7 61 OSOLD = $FFF8 97 ; 98 ; Set universal OS stuff 99 ; 0100 ; Set left margin to 0 0110 LDA #0 0120 STA RMARG 0200 ; Set background color 0210 LDA #4 0220 STA CBACK 0300 ; Set text color 0310 LDA #$0C 0320 STA CFORE 0399 ; 0499 ; Do XL/XE section? 0500 ; XLXE OS R1,R2,R3,R4 0505 LDA OSNEW 0510 CMP #5 0520 BCC XLXE 0530 ; XLXE OS R10 0540 LDA OSNEW 0550 CMP #10 0560 BEQ XLXE 0570 ; XLXE OS R11 0580 LDA OSNEW 0590 CMP #11 0600 BEQ XLXE 0610 ; No Match 0620 JMP DONE 0999 ; 1000 XLXE 1005 ; Set key repeat rate 1010 LDA #2 1020 STA KRATE 1100 ; Set key delay 1110 LDA #14 1120 STA KDELY 1200 ; No key click 1210 LDA #1 1220 STA CLICK 1899 ; 1900 DONE 1910 RTS 1920 .END
Here is a breakdown of what the program code is doing. The main differences are in lines 500 through 620.
- Lines 10-61 : Assembler directives and definitions.
- Lines 100-320 : Set the preferences that work across all Atari OS versions.
- Lines 505-520 : Comparison logic for XL/XE OS versions 1 through 4. Load the accumulator with the value from the OSNEW location. Compare the accumulator value to 5 (one higher than the values I want to include). Branch on Carry Clear (if the value is less than) to the XLXE code section.
- Lines 530-560 : Comparison logic for XL/XE OS version 10. Load the accumulator with the value from the OSNEW location. Compare the accumulator value to 10. Branch if its equal to the XLXE code section.
- Lines 570-600 : Comparison logic for XL/XE OS version 11. Load the accumulator with the value from the OSNEW location. Compare the accumulator value to 11. Branch if its equal to the XLXE code section.
- Lines 610-620 : None of the comparisons matched so we need to jump past the XLXE code section to the program completion code denoted by the label DONE.
- Lines 1000-1220 : Set the preferences that only work on Atari XL/XE OS versions.
- Lines 1900-1920 : Program completion
How do I know it works?
I made a copy of the program and added addition code to it. The additional code caused it branch to different XLXE sections which set the screen colors differently. I then tested it using different OS’s in the emulator, and saw the color differences as expected. No screenshots this time since nothing changed on the output.
Now, back to trying to print something on the screen!