Monday, March 6, 2017

Switching to 6502 Assembly for a moment ...

I wanted to handle screen backgrounds via a peek and poke system from BASIC, but it was unbelievably SLOW.  The solution?  Assembly language.  It's taken me a few weeks to get my head wrapped around 6502 assembly again (it's been a few years, after all), and managed to hammer out the following copy and replace routines; one is at 49152, one at 49206.  The first copies screen and color memory  to $C100, and the second copies it back from $C100.

So, the memory at $C100 maps out as follows:
$C100-$C4FF is a copy of screen memory (which starts at $0400 when displayed).
$C500-$C8FF is a copy of color memory (which starts at $D800 when displayed).

So, to make a copy of the screen: SYS49152
To retrieve the copy for display: SYS49206

Here's the code:

1000 *= 49152
1010 .S
1020 .O
1025 .D SP
1030 ; "SCREENPOKER"
1040 ; THIS ASSEMBLY CODE GENERATES THE
1050 ; MACHINE LANGUAGE TO PERFORM A
1060 ; COPY OF SCREEN CODE DATA FROM
1070 ; $0400 TO $C100.
1080 ;
1090 ; IN THE COMING PROGRAMMING, THE
1100 ; ROUTINE, ALLOWING A COPY AND
1110 ; PASTE FUNCTIONALITY FOR THE
1120 ; SCREEN, ALLOWING, FOR EXAMPLE,
1130 ; WINDOWS TO BE DRAWN ON THE SCRN
1140 ; AND THEN THE SCREEN RESTORED.
1150 ;
1160 LDX #$00
1170 START LDA $0400,X
1180 STA $C100,X
1190 LDA $0500,X
1200 STA $C200,X
1210 LDA $0600,X
1220 STA $C300,X
1230 LDA $0700,X
1240 STA $C400,X
1250 LDA $D800,X
1260 STA $C500,X
1270 LDA $D900,X
1280 STA $C600,X
1290 LDA $DA00,X
1300 STA $C700,X
1310 LDA $DB00,X
1320 STA $C800,X
1330 INX
1340 BNE START
1350 RTS
1360 ;
1370 ; THE NEXT SECTION OF CODE WILL
1380 ; PERFORM THE REVERSE OF THE
1390 ; PRIOR. IT WILL COPY THE SCREEN
1400 ; AND COLOR CODES FROM THE COPY
1410 ; BACK TO THE SCREEN
1420 ;
1430 LDX #$00
1440 START2 LDA $C100,X
1450 STA $0400,X
1460 LDA $C200,X
1470 STA $0500,X
1480 LDA $C300,X
1490 STA $0600,X
1500 LDA $C400,X
1510 STA $0700,X
1520 LDA $C500,X
1530 STA $D800,X
1540 LDA $C600,X
1550 STA $D900,X
1560 LDA $C700,X
1570 STA $DA00,X
1580 LDA $C800,X
1590 STA $DB00,X
1600 INX
1610 BNE START2
1620 RTS


There really should be an easier/shorter way to handle this, and I'll be looking into that in the future.  Right now, it just does an LDA/STA to and from memory, basically moving 8 256-byte blocks in pseudo-parallel.

Fun stuff.

Thursday, February 16, 2017

Retro Programming in Commodore BASIC 2.0 - Part 2

Okay.  Since the last post, I've added code to process movement.  It's very basic and doesn't handle obstacles yet, but one step at a time.

The lines of code are still there from the last post.  What's been added are:
Lines 40-90: Read the cursor keys, set the direction (DI) and call the movement subroutine.  Pressing 'space' will end the program.
Line 26: Line 26 provides initialization of the movement routines (the variables are explained below), and creates a ball (81) character at (3,3).

Lines 10020 - 10110 make up the movement subroutine.  This subroutine will likely change quite a bit as time goes on.
Line 10020 erases the current ball at the current player position.
Lines 10040 - 10100 set the values of SX and SY for plotting the character, and line 10105 jumps to the display subroutine.

Within the movement handler, the following variables have the following meaning:
UX (Upper X): The highest value for SX; this is the rightmost boundary of player movement.
UY (Upper Y): The highest value for SY; this is the bottommost boundary of player movement.
LX (Lower X): The lowest value for SX; this is the leftmost boundary of player movement.
LY (Lower Y): The lowest value for SY; this is the uppermost boundary of player movement.
DI: This is the movement direction:

  • DI = 1 : Left movement.
  • DI = 2 : Right movement.
  • DI = 3 : Movement up.
  • DI = 4 : Movement down.
The next step will be setting up a maze and configuring non-traversable walls.

Wednesday, February 15, 2017

Retro Programming in Commodore BASIC 2.0 - Part 1

Overview
It's amazing how much rust your programming skills can get for a specific machine and a specific language.  I've been programming Java professionally for about 10 years now, and am going back to my roots to rediscover the simplicity of programming for a machine with only 64k of RAM and direct access to the hardware ... no BIOS, no heavy GUI, just me and the machine.

And it's awesome!

The Program
A game.  That's about as far as I've gotten.  I'm writing this by the seat of my pants, so I'm just going to code.  I know I need screen routines and movement routines, but beyond that, I'm hashing out the details as I go.

Here's what I have so far:

It's not much.  Here's the breakdown:

Lines 10-30 are test code for the subroutines starting at line 10000:
Line 10 clears the screen, sets the cursor color to cyan, and sets the background color and border to blue.
Line 20 calls the subroutine at 10010 to put a ball character at (15, 5) on the screen in white.
Line 25 calls the subroutine at 10010 to put a ball character at (0,0) on the screen in yellow.
Line 30 is a keypress loop to hold up execution.

Line 9999 ends the program before the subroutines can be reached.  This prevents a program that doesn't exit before then from accidentally slipping into the first subroutine.

Line 10000 is just a comment.

Line 10010 contains the first subroutine.  Using 1024 as the start of screen RAM and 55296 as the start of screen color RAM, it uses the values in SX and SY to calculate the positions in screen and screen color RAM for the requested item to be displayed, and POKEs the character code and color code (CH and CO) into screen and screen color RAM.  There is no error checking; values outside of the valid ranges of 0<=SX<=39, 0<=SY<=24, 0<=CH<=255, and 0<=CO<=255 will result in an error or in the case of SX and SY, possibly lock up the computer or corrupt the program.

Next Step
Next, I'll be adding movement routines, first based on cursor keys and then based on joystick.