User:Derek Andrews/sandbox/Programming colours
Programming colours
editThis 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
editThe 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
editAll 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
edit7 | 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
edit7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
X | X | R1 | G1 | B1 | R2 | G2 | B2 |
$1FC2 Colour objects 3 & 4
edit7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
X | X | R3 | G3 | B3 | R4 | G4 | B4 |
$1FC6 Background and screen — enable and colours
edit7 | 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
editIf 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
editAll 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
editThe 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- Change the colours of the four objects to red, cyan, yellow and blue.
- Change the initial colour of the background grid to cyan.
- Change the colour of the score to purple.
Tutorial - Colours
editThis code block must be merged with the standard 'Hardware definitions' code before it can be assembled |
; 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
editThis 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