Modifying Super Extended Color BASIC

On a recent project I needed to read and write unsigned double byte values from memory. The standard version of BASIC does not include such commands so they must be accomplished using multiple commands. For reading a two byte value this is usually how it is done:

10 A = PEEK(&H6000)*256+PEEK(&H6001)


Variable A will now contain an unsigned two byte value starting from $6000. This is an example of writing a two byte value:

10 A=RND(65535)
20 POKE &H6000,A/256
30 POKE &H6001,256*(A/256-INT(A/256))


It turns out all this math was causing my recent project to slow down to unacceptable levels. So I had the idea of rewriting the Super Extended Color BASIC commands LPEEK and LPOKE to perform double byte reads and writes. Looking thru the commented source disassembly, I discovered that if it was acceptable to completely replace the functionality of the commands I had 27 bytes for LPEEK and 45 bytes for LPOKE to work with.

So I took the code from regular PEEK and and placed it where LPEEK was and change the opcode to read two bytes instead of one. This caused a problem, the standard return from a function subroutine converts the D register to a signed value from -32767 to 32766. I wanted an unsigned result from 0 to 65535. In the LIST command I discovered a bit of code that prints the line number to do exactly what I wanted.

     0050     00001 fpa0 equ $50
     002B     00002 binval equ $2b
              00003 
              00004 # Modify LPEEK to return two bytes (unsigned)
              00005  org $e573
E573 17D1CA   00006  lbsr $b740 convert FPA0 to integer in register X
E576 EC84     00007  ldd ,x read two bytes
E578 DD50     00008  std fpa0 convert Reg D to FP and return
E57A C690     00009  ldb #$90
E57C 43       00010  coma
E57D BDBC86   00011  jsr $bc86
E580 39       00012  rts


The new LPOKE function needed to read two comma separated values from the program and write the value to the address.

              00014 # Modify LPOKE to store two bytes (unsigned)
              00015  org $e545
E545 17D1F5   00016  lbsr $b73d eval expression return in X
E548 9F2B     00017  stx binval store address in binval
E54A BDB26D   00018  jsr $b26d syntax check for a comma
E54D 17D1ED   00019  lbsr $b73d eval expression return in X
E550 1F10     00020  tfr x,d transfer value to D
E552 9E2B     00021  ldx binval load address
E554 ED84     00022  std ,x store value in address
E556 39       00023  rts


After overlaying this code onto SECB, I now have a double byte version of PEEK and POKE. Soon I discovered I had a new slow down. I was filling buffers with the same byte, over and over. Like this:

10 FOR X = &H6000 TO &H64FF
20 POKE X, &H55
30 NEXT X


This turned out to be a slow method of filling memory. I needed a new command to quickly accomplish the same thing. I began looking for another command in SECB that I could replace. I decided to replace HPAINT.

              00025 # Modify HPAINT to be a memory fill command
              00026 # Example: HPAINT &H7400, &H2300, &H80
              00027 # Write byte $80 to buffer in $7400 to $96FF
              00028  org $ebf5
EBF5 17CB45   00029  lbsr $b73d eval expression return in X
EBF8 9F2B     00030  stx binval store address in binval
EBFA BDB26D   00031  jsr $b26d syntax check for a comma
EBFD 17CB3D   00032  lbsr $b73d eval expression return in X
EC00 3410     00033  pshs x
EC02 BDB26D   00034  jsr $b26d syntax check for a comma
EC05 BDB70B   00035  jsr $b70b eval expression return in B
EC08 9E2B     00036  ldx binval
EC0A 3520     00037  puls y
              00038 loop
EC0C E780     00039  stb ,x+
EC0E 313F     00040  leay -1,y
EC10 26FA     00041  bne loop
EC12 39       00042  rts
              00043  end


To test it I wrote this screen saver:


10 WIDTH 32:CLS
20 HPAINT &H3FF+RND(512),RND(128),127+RND(128)
30 GOTO 20