Jump to content

User:Derek Andrews/sandbox/Programming colours

From Wikibooks, open books for an open world

Programming colours

[edit | edit source]

This family of consoles have a very limited palette of colors to work with. The PVI has three digital (i.e. either on or off) colour signals that are connected to the red, green and blue inputs of the PAL encoder. This limits the the system to a palette of eight colours: black, red, green, blue, cyan, purple, yellow and white.

This seems simple at first sight, but is complicated by two other signals that can affect the colour on the display:

  • the OBJ/SCR output of the PVI which goes low whenever an object or a score digit is being displayed.
  • bit 5 of the 74LS138 'effects' register.

A further complication is that some consoles such as the Interton VC4000 use these signals to alter the brightness of the colour, while others use it to invert the colour. The rest of this page is applicable to the colour inversion method, specifically as implemented on the Voltmace Database.

Hardware description

[edit | edit source]
Block diagram of the colour control circuit in the Voltmace Database video game console.

The three non-inverting colour inputs to the PAL encoder are connected directly to the inverted colour outputs of the PVI: R, G, B.

The INV input to the PAL encoder is derived from a wire-AND circuit comprising an open-collector transistor INVERT, the open-drain OBJ/SCR and a pull-up resistor. Either one of those devices can pull the invert input to a low logic level.

The INVERT signal is set by writing to bit 5 of the hex D-type flip-flop, 74LS378, at memory address $1E80. Writing a 1 to that bit causes the transistor to turn on, and pull the INV input to the PAL encoder to a logic 0 irrespective of the state of OBJ/SCR.

Registers

[edit | edit source]

All the colour information is controlled by four registers, three in the PVI and one logic chip. Note that these registers are all write-only. It is up to the programmer to keep track of what is in them.

$1E80 'Effects' register

[edit | edit source]
7 6 5 4 3 2 1 0
- - INVERT - - - - -

The other bits in this register are used by the audio circuitry.

$1FC1 Colour objects 1 & 2

[edit | edit source]
7 6 5 4 3 2 1 0
X X R1 G1 B1 R2 G2 B2

$1FC2 Colour objects 3 & 4

[edit | edit source]
7 6 5 4 3 2 1 0
X X R3 G3 B3 R4 G4 B4

$1FC6 Background and screen — enable and colours

[edit | edit source]
7 6 5 4 3 2 1 0
X R G B Background

Enable

R G B
X Background colour Screen colour

If Background Enable is set to zero, both the screen and background grid are output from the PVI as '111'.

If the background grid is not used for graphics, the registers that define it, $1F80 - $1FAC, may be used for variable storage. They are hidden on the display by setting background and screen to the same colour.

Colours

[edit | edit source]

If you find the hardware description hard to follow with the multiple inversions, you aren't alone. All you really need to do is use the table below when programming colours.

COLOUR OBJECTS BACKGROUND or SCREEN
Invert 0 Invert 1
BLACK 111 000 111
BLUE 110 001 110
GREEN 101 010 101
CYAN 100 011 100
RED 011 100 011
PURPLE 010 101 010
YELLOW 001 110 001
WHITE 000 111 000

The score colour cannot be programmed independently; it is always the inverse of the colour programmed for the background.

Neither the object colours or the score colour are affected by the state of bit 5 of the 74LS138 'effects' register since the OBJ/SCR will be low while they are being displayed.

The INVERT bit is used in some games such as Interton's Super Space as a screen-saver. While it is tempting to normally set the INVERT bit to 0, it might be better to have it normally set to 1. In this way the colour codes are the same for objects, score, background and screen, and will be in negative logic, i.e. a 0 turns the colour on.

Code snippets

[edit | edit source]

All the colours are set by these four registers:

effects     equ $1E80
colours12   equ $1FC1
colours34   equ $1FC2
backgnd     equ $1FC6

It is a good idea to clear the effects register early on in your program. This will not only turn off the colour inversion, but will also turn off the audio.

        eorz    r0
        stra,r0 effects		

Alternatively, as discussed above, the audio can be turned off and the colour inversion turned on so that all colours can be programmed with the same codes.

        lodi,r0 $20
        stra,r0 effects		

Remember that the objects colours are always active low, so the RGB sequence 101 would appear as green, etc:

        lodi,r0 %00010101       ; XX  /  011     /   110
        stra,r0 colours12       ;     / obj1 red / obj2 blue

The background and screen colours depend on the state of the invert bit. When the invert bit is 0, their colours are always active high, so the RGB sequence 010 would appear as green, etc:

        eorz    r0
        stra,r0 effects         ; invert bit = 0	
        lodi,r0 %00001110       ;  X / 100            /   1     / 001
        stra,r0 backgnd         ;    / background red / enabled / screen blue

Conversely, when the invert bit is 1, their colours are active low, so the RGB sequence 101 would appear as green, etc:

        lodi,r0 $20
        stra,r0 effects         ; invert bit = 1	
        lodi,r0 %00001110       ;  X / 011            /   1     / 110
        stra,r0 backgnd         ;    / background red / enabled / screen blue

Tutorial program

[edit | edit source]
Demonstration of colour programming on the Voltmace Database games console

The code for this tutorial can be found in the Appendices: Tutorial code, Programming colours. When this program is run, you should see a static screen that looks like this:

The fours objects are programmed in different colours. When the first row of objects have been displayed, the INVERT bit in the effects register is set to one. This inverts the colour of the screen (yellow 110 becomes blue 001) and the background switches from black to white.

Notice that the objects and the score digits are the same above and below this transition. Also note that the score is the inverse of the colour programmed for the background.

Exercises

[edit | edit source]
  1. Change the colours of the four objects to red, cyan, yellow and blue.
  2. Change the initial colour of the background grid to cyan.
  3. Change the colour of the score to purple.

Tutorial - Colours

[edit | edit source]
; Tutorial  Colours
;=============================================================================
        org     0
reset_vector:                   ; the microprocessor starts here when the reset button is pressed
        bcta,un reset
        org     3
interrupt_vector:               ; interrupts shouldn't happen, but we set this just in case
        retc,un
reset:  
                                ;initialise program status word, just to be sure!
        ppsu    intinhibit      ;inhibit interrupts
        cpsu    stackpointer    ;stack pointer=%000
        cpsl    registerselect  ;register bank 0
        cpsl    withcarry       ;without carry
        cpsl    compare         ;arithmetic compare

        eorz    r0
        stra,r0 effects         ;initialise the 74LS378
        stra,r0 objectsize      ;all objects size 0
        bsta,un DefineObjects   ;define all objects 
        bsta,un DefineGrid      ;define the grid
        lodi,r0 $67
        stra,r0 score12
        lodi,r0 $89
        stra,r0 score34
        lodi,r0 %00001110       ;  X / 000              /   1     / 110
        stra,r0 backgnd         ;    / black background / enabled / yellow screen
        bsta,un Vsync0          ; make sure VRST hasn't started
endless:
        bsta,un Vsync1          ; wait for VRST to start
        eorz    r0
        stra,r0 effects         ; turn off colour invert
        stra,r0 scoreformat     ; 2 + 2 score digits at top  (see Tutorial......)
        lodi,r0 %00010101       ; XX  /  010        /   101
        stra,r0 colours12       ;     / obj1 purple / obj2 green
        lodi,r0 %00111000       ; XX  /  111        /   000
        stra,r0 colours34               ;     / obj 3 black / 4 white
        bsta,un Vsync0          ; wait for VRST to end 
        lodi,r1 1
        bsta,un WaitObj         ; wait for object 4 to complete  (see Tutorial......)
        lodi,r0 $20
        stra,r0 effects         ; turn on colour invert
        lodi,r0 3
        stra,r0 scoreformat     ; 4 score digits at bottom
        bctr,un endless

;===================================================================
; subroutine  -  define shapes and position of all objects
                        ; (see Tutorial......)
DefineObjects:
        lodi,r3 $0A
        lodi,r0 $FF
loopDS:                         
        stra,r0 shape1,r3-      ; create rectangular shapes
        stra,r0 shape2,r3
        stra,r0 shape3,r3
        stra,r0 shape4,r3
        brnr,r3 loopDS
        lodi,r0 40              ; set their positions
        stra,r0 hc1
        stra,r0 hcd1
        lodi,r0 60
        stra,r0 hc2
        stra,r0 hcd2
        lodi,r0 80              
        stra,r0 hc3
        stra,r0 hcd3
        lodi,r0 100
        stra,r0 hc4
        stra,r0 hcd4
        lodi,r0 88
        stra,r0 vc1
        stra,r0 voff1
        stra,r0 vc2
        stra,r0 voff2
        stra,r0 vc3
        stra,r0 voff3
        stra,r0 vc4
        stra,r0 voff4
        retc,un
;=================================================================
; subroutine  -  define background grid
                        ; (see Tutorial......)
DefineGrid:
        lodi,r0 $FF
        stra,r0 $1f80
        stra,r0 $1fa4
        lodi,r0 $FE
        stra,r0 $1f81
        stra,r0 $1fa5

        lodi,r3 $81
loopDG: 
    lodi,r0     $80
        stra,r0 $1f00,r3+
        lodi,r0 $01
        stra,r0 $1f00,r3+
        comi,r3 $a3
        bcfr,eq loopDG
        lodi,r0 $01
        stra,r0 $1fa8
        lodi,r0 $08
        stra,r0 $1fac
        lodi,r0 $00
        stra,r0 $1fa9
        stra,r0 $1faa
        stra,r0 $1fab
        stra,r0 $1fa6
        stra,r0 $1fa7
        retc,un
;=================================================================
; subroutine - wait for vertical reset to clear
                        ; (see Tutorial......)
Vsync0:
        tpsu    sense
        bctr,eq Vsync0          ; wait for Sense bit to clear
        retc,un
;=================================================================
; subroutine - wait for vertical reset to set
Vsync1:         
        tpsu    sense           ; wait for Sense bit to be set
        bctr,lt Vsync1
        retc,un
;=================================================================
;subroutine - wait for object to finish
                        ; (see Tutorial......)
;  enter with r1=mask for bit to be tested:
;       obj1=$08, obj2=$04, obj3=$02, obj4=$01
WaitObj:
        loda,r0 objectstatus
        andz    r1
        bctr,eq waitobj
        retc,un

Hardware definitions

[edit | edit source]

This is a standard block of assembler directives that give names to constants and memory addresses of all the registers in the system

;============================================================
; PROCESSOR CONSTANTS
; -------------------
carrybit        equ $01
compare         equ $02
withcarry       equ $08
registerselect  equ $10
intinhibit      equ $20
stackpointer    equ $07
sense           equ $80
flag            equ $40

; EFFECTS REGISTER
; ----------------
effects         equ $1e80

; BUTTONS
; --------
player1keys147c equ $1E88 ;player1 keypad, bits: 1,4,7,clear,x,x,x,x
player1keys2580 equ $1E89 ;player1 keypad, bits: 2,5,8,0,x,x,x,x
player1keys369e equ $1E8A ;player1 keypad, bits: 3,6,9,enter,x,x,x,x
player2keys147c equ $1E8C ;player1 keypad, bits: 1,4,7,clear,x,x,x,x
player2keys2580 equ $1E8D ;player1 keypad, bits: 2,5,8,0,x,x,x,x
player2keys369e equ $1E8E ;player1 keypad, bits: 3,6,9,enter,x,x,x,x
keymask123      equ $80     ;top row of keys
keymask456      equ $40
keymask789      equ $20
keymaskc0e      equ $10     ;bottom row of keys
console         equ $1E8B ;start and select buttons on console
consolestart    equ $40
consoleselect   equ $80


; PVI ADDRESSES AND CONSTANTS
; ---------------------------
object1      equ $1F00
shape1       equ $1F00
hc1          equ $1F0A ; hc = Horizontal Coordinate
hcd1         equ $1F0B ; hcd = Horizontal Coordinate Duplicate
vc1          equ $1F0C ; vc = Vertical Coordinate
voff1        equ $1F0D ; voff = Vertical Offset

object2      equ $1F10
shape2       equ $1F10
hc2          equ $1F1A 
hcd2         equ $1F1B 
vc2          equ $1F1C 
voff2        equ $1F1D 

object3      equ $1F20
shape3       equ $1F20
hc3          equ $1F2A 
hcd3         equ $1F2B 
vc3          equ $1F2C 
voff3        equ $1F2D

object4      equ $1F40
shape4       equ $1F40
hc4          equ $1F4A 
hcd4         equ $1F4B 
vc4          equ $1F4C 
voff4        equ $1F4D  

objectsize   equ $1FC0

colours12    equ $1FC1
colours34    equ $1FC2
backgnd      equ $1FC6

pitch        equ $1FC7

scoreformat  equ $1FC3
score12      equ $1FC8
score34      equ $1FC9

objectstatus equ $1FCA
collisions   equ $1FCB
adpot1       equ $1FCC
adpot2       equ $1FCD