Videopac G7000 BIOS
Last changed: 2004-08-31

Bit fields and keyboard

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.

The routines

Bit test, bit set, bit clear

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.

Waitforkey

The keyboard routine is very simple to use, it waits until a key is pressed and returns the key in A.

The program

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

Changing the active grid line

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

Set/clear the current bit

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