Videopac G7000 BIOS
Last changed: 2003-07-22

Creating programs on the G7000 / Odyssey²

Which assembler to use

To assemble your programs you need an assembler for the Intel 8048 processor which is a member of the MCS-48 processor family. For the demo programs in this document I used the freeware assembler ASL. I used the Linux version, but there are also DOS and OS/2 versions available there.

Using ASL

ASL does not generate a ROM file directly, it uses an intermediate file with the extension ".p". There are several tools included in the ASL package that can convert these ".p" files. Use p2bin to generate binary files. It needs to know which address range to extract from the ".p" file. The internal BIOS of the G7000 / Odyssey² occupies the first 1KByte. Nearly all commercial cartridges use only the next 2KByte, so to generate a ROM file for use with o2em the range you need is from 0400h to 0bffh. To mark parameters as hexadecimal p2bin uses the $ sign which needs to be escaped by most shells. So it is more portable to use decimal numbers. To assemble the hello.a48 demo program into a o2em ROM file you need to type:


asl hello.a48
p2bin hello.p hello.rom -r 1024-3071

This example is for Linux, the executable of the DOS version is called AS.EXE, so you have to substitute asl with as in the example when using DOS. For the G7000RAM you need to copy the range 1024-4095. Later versions of o2em support 3K per bank, so there is no longer a difference between o2em and the G7000RAM.

All these examples are for programs with only one G7000 / Odyssey² program bank. For bigger programs I can think of several methods to handle them. The method I currently prefer is to use one assembler file per program bank. It takes takes some time to fill the 2KBytes available with o2em. So if your code reaches that size you will be experienced enough to find the way which is best for your code.

How to get the binary into the machine

After assembling your programs you have to find a way to run them. You can run the programs on the o2em emulator. If you prefer to test your programs on a real machine you can use the G7000RAM cart. It is a 12K (4×3K) RAM cart with a serial port (RS232) to upload the programs. Find out how to build one on my home page. If you can burn EPROMs you can build an EPROM cart, eg. by hacking an existing cart.

Conventions used in this document

All numbers in hex are written as 0ABCDh in this document. A means the A register of the 8048, R0-R7 the active register bank, most of the time this is RB1. When writing R0:5-7 I mean bit 5-7 of register R0. RB0 and RB1 are a specific register bank, MB0 and MB1 are the program memory banks. P0, P1 and P2 are the external ports. F0 and F1 are flags internal to the 8048. T is the timer register. 256 bytes together on a 256 byte boundary are one page. All symbolic labels for the BIOS routines in this document are explained in the summary chapter and are included into g7000.h. Symbolic names for VDC registers start with vdc_, those for internal RAM start with iram_. The names for external RAM start with eram_. Names starting with col_ are names for colours.

The beginning

At power on or after reset the BIOS jumps directly to 0400h, the first address of the external ROM. Normally you put a jmp selectgame = 02C3h there, this initialises the VDC, internal and external RAM. Then it displays the "SELECT GAME" message and waits for a key. After that it jumps to 0408h. There you have to start your code with another jmp, because 040Ah is used by the interrupt. Which key was pressed is stored in A. All sprites, chars, quads and the grids are initialised, the VDC is enabled and the graphics are on.

Getting the interrupt chain right

If an external interrupt occurs, the BIOS jumps to 0402h. From there you can insert some code into the interrupt. After that do a jmp 0009h, I call this irq. The BIOS checks for VSYNC (Vertical sync, marks the beginning of a new frame) and jumps to 0406h, if VSYNC. Here you can insert again some code. Continue to vsyncirq = 001Ah. After processing the register transfer table the BIOS jumps to 040Ah, if there is a sound event to process. Again you can insert some code here. The sound event gets processed at soundirq = 0044h. So if you don't want to insert code anywhere into the interrupt the beginning of your program looks like:


        include "g7000.h"

        org     0400h

        jmp     selectgame
        jmp     irq
        jmp     timer
        jmp     vsyncirq
        jmp     start
        jmp     soundirq

timer   retr            ; timer interrupts are discussed later
start                   ; your code starts here

Displaying Characters: Hello World

In this section I will explain my hello.a48 program. It is very important not to change the VDC registers while displaying graphics, at least not if you want predictable results. So there are two routines to turn the graphics off (gfxoff = 11Ch) and on (gfxon = 0127h). To display characters there is printchar = 03EAh. You put a pointer to the character to display into R0, for example vdc_char0 = 010h as the first character. In R3/R4 you put the X/Y position on the screen. R6 is the colour of the character, for example col_char_white = 00Eh. In R5 you tell which character to display. After calling printchar, R0 is set to the next character and R3 is advanced right for 8 pixels, so you can print several characters into one line. The following code prints the traditional "HELLO WORLD" onto the screen.


start
        call    gfxoff              ; switch the graphics off
        mov     r0,#vdc_char0       ; start char
        mov     r3,#20h             ; x-position
        mov     r4,#20h             ; y-position
        mov     r2,#0Bh             ; length
        mov     r1,#hellostr & 0FFh ; the string to print
                                    ; must be in the same page
loop    mov     a,r1                ; get pointer
        movp    a,@a                ; get char
        mov     r5,a                ; into to right register
        inc     r1                  ; advance pointer
        mov     r6,#col_chr_white   ; colour
        call    printchar           ; print it
        djnz    r2,loop             ; do it again
        call    gfxon               ; lets see what is written
stop    jmp     stop                ; Thats all

hellostr db     1Dh, 12h, 0Eh, 0Eh, 17h, 0Ch
         db     11h, 17h, 13h, 0Eh, 1Ah