This is the first of what I hope will turn into a series of posts that will help the newcomer to programming the Voltmace Database, Interton VC4000 and related TV video game consoles. I will cover both the microprocessor and the video chip. I will assume some basic knowledge of assembler programming but will try to provide links to other websites to explain some fundamentals that I don’t want to get bogged down in here. Please leave comments or use the contact page if you have any questions.
I will be using examples of real code as much as possible, taken from my Leapfrog program, details of which you can find via the Links page of this site. On that page you can also find links to data sheets for both the 2650 microprocessor and the 2636 programmable video interface, or PVI.
START: lodi,r3 H'AA' ;blank the score digits stra,r3 score12 stra,r3 score34 lodi,r3 H'C8' ;clear all other PVI registers loop0015: stra,r0 object1SHAPE,r3,- brnr,r3 loop0015
All mnemonics in the 2650 instruction set are 3 or 4 characters long. In most cases the first three characters tell us what the instruction is going to do, and the fourth one tells us what addressing mode it will use. In the example above there are three types of instruction:
- lod – Load a register with data.
- str – Store the contents of a register.
- brn – Branch to another location in the program.
The three types of addressing mode used in this example are:
- i – immediate addressing
- a – absolute addressing
- r – relative addressing
So lets look as the example line by line and explain these in a little more detail.
lodi,r3 H’AA’ – this tells the processor to load register r3 with the data byte immediately specified in the instruction itself which in this case is the Hexadecimal value AA.
stra,r3 score12, and stra,r3 score34 both tell the processor to store the contents of register r3 in the absolute memory addresses labelled score12 and score34. These have been defined elsewhere in the program as memory addresses 1FC8 and 1FC9 which in our circuit are two registers in the PVI that define the four characters that can be displayed as score values at the top or bottom of the screen. Each nibble represents one character, 0-9. Hexadecimal values A-F cause the digit to be blank.
The effect then of these first three instructions is to blank the score digits.
lodi,r3 H’C8′ you should now be able to figure this out for yourself.
stra,r0 object1SHAPE,r3,- is a more complicated instruction, but very powerful. The first part is straightforward. The contents of register r0 are going to be stored somewhere. That ‘somewhere’ is defined by object1SHAPE,r3,- . What happens here is the final address is calculated by subtracting 1 from the value if r3 and adding that to the address defined by object1SHAPE , then saving r0 in the resulting address.
This is what is called indexed addressing. In this case the index register is r3.
The – sign at the end of the line indicates that the index register will be automatically decremented before the store operation. This is known as pre-indexing. Some other microprocessors use post-indexing where the decrement is performed after the data is stored, but the 2650 always does the decrement first.
The 2650 can also do an auto-increment. This would be shown by a + sign at the end of the line: stra,r0 object1SHAPE,r3,+ Again, the increment would be done before the data is stored.
A final option would be to use the index register without changing it: stra,r0 object1SHAPE,r3
brnr,r3 loop0015 – this causes the program execution to branch to program location loop0015, but only if r3 does not equal 0. The mnemonic brn stands for Branch on Register Non-zero. It uses relative addressing as indicated by the r at the end of the mnemonic. This addressing mode uses one less byte of code than absolute addressing, but can only jump to a location within about 128 bytes of the current instruction.
These two lines therefore execute repeatedly until r3 is decremented to zero. The value of object1SHAPE is 1F00. The first time around the loop, the data in r0 is stored in 1F00+C8-1, or 1FC7. The last time around it is stored in 1F00. Register r3 is now 0 so the branch back to loop0015 is not taken and the processor moves on to the next instruction.
We will use code like this wherever we want to work with a block of data.