For people born in the seventies, 6502 is a magic number. It was the name of one of the most used processors in electronic devices of the eighties such as the Apple 2, the commodore 64, the nintendo NES e.t.c.
For me everything started there. I did not write any assembly codes for years but at the beginning of my career, this was still something you write on a résumé.
Writing 6502 codes in the old days was a nightmare. Some assembler tools like MERLIN helped a lot but it has nothing in common with the modern technology we are using nowadays.
- This is a 8 bits processor, so it can only add numbers between 0 and 255. Overflows must be checked manually to handle additions that result in a number bigger than 255.
- There was no memory protection. It was possible to write anywhere in the memory. It was even possible to change the instructions of your own software dynamically.
- The stack was limited to 256 bytes.
- The main memory of this kind of machines most often don’t exceed 64 KB including the video memory.
- The regular clock speed of the 6502 was 1Mhz
Even with all these limitations, it was possible to write incredible software by using tricks that did not make the code easily maintainable but make it efficient.
So I will add a small example of how to create a FillRect subroutine using this processor. Note that the emulator uses a low resolution graphic mode that starts at memory $200, is 0x20 pixels large and has 20 lines. So the third pixel of line 2 is at address 200+20+2 => $222.
The following program will draw three rectangles using page zero to pass parameters to the subroutines.
; FIRST RECT LDA #$0A ; WIDTH STA $10 LDA #$0F ; HEIGHT STA $11 LDA #$24 ; UPPER RIGHT CORNER ADDRESS in memory LOWER BYTE STA $12 LDA #$02 ; LOWER RIGHT CORNER ADDRESS in memory LOWER BYTE STA $13 LDA #$0F ; COLOR STA $14 JSR fillrect ; SECOND RECT LDA #$14 ; WIDTH STA $10 LDA #$04 ; HEIGHT STA $11 LDA #$07 ; UPPER RIGHT CORNER ADDRESS in memory LOWER BYTE STA $12 LDA #$03 ; LOWER RIGHT CORNER ADDRESS in memory LOWER BYTE STA $13 LDA #$02 ; COLOR STA $14 JSR fillrect ; THIRD RECT LDA #$7 ; WIDTH STA $10 LDA #$0F ; HEIGHT STA $11 LDA #$12 ; UPPER RIGHT CORNER ADDRESS in memory LOWER BYTE STA $12 LDA #$04 ; LOWER RIGHT CORNER ADDRESS in memory LOWER BYTE STA $13 LDA #$03 ; COLOR STA $14 JSR fillrect BRK ;============ DRAW LINE ; COLOR IS STORED at ADDRESS $14 ; WIDTH of the line at ADDRESS $10 ; START POINT at ADDRESS $12 (Indirect 2 bytes) ;============ DRAW LINE drawline: LDA $14 ; LOAD THE COLOR IN A LDY $10 ; LOAD WIDTH IN Y drawlineloop: STA ($12),Y ; STORE A AT ADDRESS (POINTED BY $12)+Y DEY ; DECREMENT Y CPY #$00 ; IS THE LINE FINISHED BNE drawlineloop RTS ;============ FILL RECT ; COLOR IS STORED at ADDRESS $14 ; WIDTH of the rect at ADDRESS $10 ; HEIGHT of the rect at ADDRESS $11 ; START POINT at ADDRESS $12 (Indirect 2 bytes) ;============ FILL RECT fillrect: LDX $11 ; HEIGHT fillrectloop: JSR drawline DEX ; DECREMENT HEIGHT LDA $12 ; LOWER BYTE OF START POINT CLC ; CLEAR CARRY ADC #$20 ; MOVE TO THE NEXT LINE BCC nocarry ; BRANCH IF NO CARRY INC $13 ; IF CARRY THEN ADD 1 TO THE HIGHER BYTE nocarry: STA $12 ; STORE THE LOWER BYTE CPX #$00 ; IS IT THE LAST LINE ? BNE fillrectloop RTS
Simply copy the code in the source in one of the emulators available here.You should end up after pushing the “assemble” and then the “run” button with the nice picture below.
Note that the full code is 104 bytes long but that the two routines (Fill rect and drawline) only use 33 bytes ! There are other ways to write the same code and it is probably not the most efficient one, but at least it is readable.
For old geeks note that Jordan Mechner, developper of eighties games such as Karateka and Prince of Persia, open sourced the Apple 2 code of Prince of Persia, which definitively pushed the Apple 2 to its limits.
Happy coding 🙂