This demo program
demonstrates how to manipulate single bits in external RAM or VDC registers. A
bit field consists of several bytes in external memory accessed via
movx. It can be used to mark some members of a group of objects.
For example a card deck from which cards can be drawn randomly. To keep track
which card is already drawn a bit field can be used.
Another feature explained in this chapter is the use of the keyboard. The program also uses VSYNC IRQ to blink and line interrupts to change colours mid screen, but this is discussed later in the next chapter.
All the bit-field routines are not available on the Videopac+ G7400. Any program using them is not compatible with the Videopac+ G7400 and will crash. The keyboard routine is available on both machines.
The bit field used is the horizontal grid, so any changes are immediately
visible on the screen. One grid line is active, this line blinks. With the
keys "+" and "-" the next/previous grid line gets
active. To set/clear the active grid line use the keys "1" and
"0". So the program is a very simple grid editor, but many things
are missing, there is no vertical grid, the last line of the horizontal grid is
missing and there is no way to transfer the result to anything. As usual there
are no range checks so leaving the screen crashes the system. If you want to
finish it and mutate it into a real grid editor, please contact me first, I
plan to do it myself sometime.
All the bit field routines need a pointer to the end of the bit field in R1. The number of the bit to manipulate has to be put into A. After calling one of the routines A contains the old status, R1 points to the byte in which the bit is in and R2 contains a bit mask with the bit set which was requested.
The keyboard routine is very simple to use, it waits until a key is pressed and returns the key in A.
As usual I leave out all the initialisations and start with the main loop.
I wait until the user presses a key, store it for later use, test for
"+" and "-", adjusting R6 accordingly and test if the
active grid has changed.
main ; begin of main loop
call waitforkey ; let user press a key
mov r7,a ; store it for later
mov r0,#iram_work
mov a,@r0 ; get active bit
mov r6,a ; new bit, if any
mov r5,a ; old bit
mov a,r7
xrl a,#010h ; "+" key
jnz noplus
inc r6
noplus
mov a,r7
xrl a,#028h ; "-" key
jnz nominus
dec r6
nominus
; test, if bit changed
mov a,r5
xrl a,r6
jz nonewbit ; not changed
I have to change the active grid line, but the routine which blinks runs in
the IRQ, so to avoid problems I disable the interrupts. It is not possible to
use gfxoff while the interrupts are disabled, because
gfxoff needs to disable them too and enables them afterwards, so I
call it before.
First I set iram_work to the new active bit, R0 still points to
the right location. The old active grid line was blinking, so I have to
set/reset it according to the old saved state in iram_value. So I
call bitset or bitclear setting the old grid line to
the value stored in iram_value. After that I save the contents of
the new grid line in iram_value. Then I can enable the IRQ again
to let the new current line blink.
; the user wants a new bit
; we play with the same registers as our irq
; so disable irq while changing bits
; we need access to VDC, gfxoff re-enables irq
; so turn gfx off before the irq
call gfxoff
dis i
; set new bit active, r0==iram_work
mov a,r6
mov @r0,a
; set old bit to value
mov r1,#vdc_gridh8+1
mov r0,#iram_value
mov a,@r0
jnz setoldbit
mov a,r5
call bitclear
jmp nooldbit
setoldbit
mov a,r5
call bitset
nooldbit
; set value to new bit
mov r1,#vdc_gridh8+1
mov a,r6
call bittest
mov r0,#iram_value
mov @r0,a
en i
call gfxon ; outside of dis/en i
nonewbit
I still have to process the "0" and "1" keys, so
I use the key number stored at the beginning, and set iram_value
to 0 or 0FFh if one of these keys is pressed. The grid line is set to
iram_value when changing the active grid line by the code
above.
; now test for "0" and "1"
; the key which is pressed is still in r7
mov r0,#iram_value
mov a,r7
xrl a,#0 ; "0"
jnz nozero
mov @r0,a ; a == 0, because jnz
nozero
mov a,r7
xrl a,#1 ; "1"
jnz noone
cpl a ; a == 0, because jnz
mov @r0,a
noone
jmp main