Videopac G7000 BIOS
Last changed: 2006-09-22

The Videopac+ G7400

To support the additional graphics and the new "SELECT GAME" screen the BIOS of the Videopac+ G7400 is modified at 153 bytes. To make room for this modifications the routines for bit-fields and random number generation were removed.

Here I present vpplus.a48 to show how to use the Videopac+ G7400. Most of the code is quite simple and not explained further. It displays text with different attributes. Use the key "C" to toggle conceal mode, "B" to box mode, "L" to toggle blinking and "V" to display a VDC character over the boxed text.

The additional hardware

The new hardware consists of the EF9340/EF9341 display processor designed by Thomson Semiconductors. I have found a data-sheet at Alldatasheet.com. You have to enter EF9340 into the search field yourself, a direct link did not work for me. If you know other sources please let me know.

The chip is designed for Teletext like displays. It can display a 40×24 text mode with 8 colors. The size of the chars are 8×10 pixels. It is possible to redefine up to 96 chars with default background color and another 96 chars with explicit background color. The first line of the display is called service row and quite independent from the rest of the display. The chip supports 2 different kind of attributes, parallel and serial. Parallel attributes can be set with every char, changing serial attributes requires one char space. Parallel attributes are text color, double height and width, inverted display, blinking. Block graphic chars support background color as parallel, for normal chars the background color is a serial attribute. Other serial attributes are concealed, box mode and underlining. Concealed chars can be hidden by setting a control bit. In box mode it is possible to make parts of the display transparent. This is not used on the Videopac+ G7400, you can only use box mode to turn the screen black outside the box zone. If pin B of the cartridge is not grounded even the VDC graphics are blanked outside the box zone. This can be used to apply the black border that is normally around plus graphics to VDC graphics. On o2em you can emulate this effect by putting the ASCII string "OPNB" at 040Ch.

Discovering the machine type

To find out on what kind of machine your program is running call plusselectgame instead of selectgame. Due to a clever positioned nop both routines are identical on the non-plus Videopac. On a Videopac+ G7400 the program continues in bank 1, not in bank 3 as usual. There you can set up some background graphics just like the games which were re-released for the VP+. After that you can jump to plusstart which simulates the result of the normal selectgame routine. Instead of setting up just one background for the whole game you could also just set a flag in RAM and use this later to display VP+ graphics.

Mixing VDC and VP+ graphics

The VP+ graphics is always behind all other graphic objects. To be able to see the VP+ graphics it is possible to define any combination of the 8 VDC colors as transparent. This is done by a routine called plusmode. Every bit in R7 corresponds to a VDC color. If the bit is 0, the color will be transparent. With A you can set the luminance of the 8 VP+ colors in a similar way, if the bit is 0 the color gets brighter. Any object drawn in a bright color is active for collisions with normal videopac objects. The collisions are flagged as external, vdc_coll_ext. A shortcut to hide all VP+ graphics is called plushide.

Drawing characters

Before you can access the VP+ graphic registers you have to call plusenable, just like for VDC and external RAM. Then you can call plusdata to draw chars on the screen. In R7 you put the ASCII code of the char you want to draw. From 000h-01Fh there are some accented chars. The range from 020h-07Fh is mostly normal ASCII. The chars 0A0h-0FFh are user definable. This leaves 080h-09Fh for the serial attributes.

In R6 you have to put the parallel attribute for the char. Bits 0-2 define the color of the char. Setting bit 3 (col_patr_stable) prevents the char from blinking. If bit 4 (col_patr_dhght) is set the char is displayed with double height. To double the width set bit 5 (col_patr_dwdth). The EF9340/41 chips have some limitations when doubling chars, they can't display top and bottom parts in the same line and left and right parts in the same column. With bit 6 (col_patr_invrt) it is possible to invert the char.

Setting bit 7 (col_patr_blck) changes to block graphics. Bits 4-6 of the attribute are now the new background color for the rest of the current line, so you can neither double nor invert block gfx chars. Bit 3 still prevents blinking. The char byte has a new meaning, too. From 000h-07Fh bits 0-5 form a 2×3 bitmap. If bit 6 (plus_blck_full) is cleared there are small lines between the blocks, if it is set the blocks touch each other. 080h-09Fh are marked as ILLEGAL in the data-sheet, so do not use them. 0A0h-0FFh are the second set of user definable chars, they have the background color as parallel attribute.

Setting the cursor position

By calling pluscmd you can send several commands to the VP+ graphics engine. Among them are commands to move the cursor.

To set the cursor to the first column in any line set R7 to plus_cmd_brow. Put the line number into R6. The first line (service row) is special, its position is 01Fh. The second line is numbered 0 (or 020h). Similar is plus_cmd_loady, the y position is set, but this time the x position is unchanged. To set the x position of the cursor set R7 to plus_cmd_loadx. Set R6 to 0 for the first column, to 1 for the second column etc. The last command to move the cursor is plus_cmd_incc. This one advances the cursor one char.

Command load R: some global parameters

This command sets the R register. It has its own routine called plusloadr. It takes the display mode in A. This mode is composed by 8 single bits. Setting bit 7 (plus_loadr_blnk) enables the blink mode, everything where col_patr_stable is not set blinks. Bit 6 in the R register switches between 50 and 60Hz mode. This is handled by the BIOS, it gets always set on my machine which means 50Hz. Bit 5 should always be left to 0, it changes the width of the HSYNC pulse. Setting bit 4 (plus_loadr_crsr) enables a visible cursor. Bit 3 (plus_loadr_srow) enables the display of the service row (the first line), bit 0 (plus_loadr_dspl) enables the rest of the display. When setting bit 2 (plus_loadr_conc) all chars with the col_satr_conc attribute set are hidden. Setting bit 1 (plus_loadr_box) hides all chars except the ones with col_satr_box set.

This routine is only safe when inside the VBLANK period. Otherwise parts of the screen memory get trashed. So always call waitvsync immediately before using plusloadr.

Scrolling with plus_cmd_loady0

This command sets the line number which gets displayed as second line. So you can scroll lines very easily, but the first line (service row) always stays as the first line. Set the line number into bits 0-4 of the parameter byte and set bit 5 (plus_loady0_zom) to display every line (except the first) with double height. Characters which have col_patr_dhght set are doubled again, so they are now 4 times as high as normal.

Using plus_cmd_loadm: user definable chars

There are 2 different ranges for user definable chars. One with doubling and inverting as parallel attributes and one with background color. To define a char you have to put it under the cursor. Normally the cursor advances to the next screen position when printing a char. To turn this off send the command plus_cmd_loadm with the parameter plus_loadm_wrni. Then print the char you want to redefine. Now use plus_cmd_loadm to switch to plus_loadm_wrsl. The next 10 bytes written with plusdata define the char. To redefine the next char switch back to plus_loadm_wrni, print it, switch to plus_loadm_wrsl and send the next 10 char bytes. To put the cursor back to auto advance use plus_loadm_wr. Here is some code to redefine the char 0A0h into a smiling face:


        mov     r7,#plus_cmd_loadm
        mov     r6,#plus_loadm_wrni
        call    pluscmd         ; do not move cursor
        mov     r6,#000h
        mov     r7,#0A0h
        call    plusdata        ; print char to define
        mov     r7,#plus_cmd_loadm
        mov     r6,#plus_loadm_wrsl
        call    pluscmd         ; char bitmap follows
        mov     r2,#chardata & 0FFh
        mov     r3,#10
.char   call    getchar
        mov     r6,a
        mov     r7,a
        call    plusdata
        inc     r2
        djnz    r3,.char

        ; back to normal
        mov     r7,#plus_cmd_loadm
        mov     r6,#plus_loadm_wr
        call    pluscmd         ; draw normal chars

        [...]

; get char data
getchar mov     a,r2
        movp    a,@a
        ret

chardata
        db      00111100b
        db      01000010b
        db      10000001b
        db      10100101b
        db      10000001b
        db      10100101b
        db      10011001b
        db      10000001b
        db      01000010b
        db      00111100b

If you have to define a lot of chars it is faster to turn off the display by clearing plus_loadr_dspl and plus_loadr_srow. That way the chip has more bandwidth available on its bus.

More plus_cmd_loadm: reading data

For any of the aforementioned plus_loadm_ write modes there is a corresponding read mode, but there is no routine to read the data in the BIOS. So you have to read it manually. The data-sheet is not very clear is this aspect, it seems that the chip needs a dummy read from its TB register to fetch the data. Additionally you have to check the busy flag by calling plusready. Here is some example code how to use plus_loadm_rdni. This is just my test code, it is not included into any demo program.


        mov     r7,#plus_cmd_loadm
        mov     r6,#plus_loadm_rdni
        call    pluscmd
        call    plusready       ; wait until mode switched
        mov     r0,#vpp_tb_rd
        movx    a,@r0           ; trigger read
        call    plusready       ; wait until read finished
        mov     r0,#vpp_ta_rd
        movx    a,@r0           ; TA
        mov     r2,a
        inc     r0
        movx    a,@r0           ; TB
        mov     r3,a

Writing directly to the VPP

If you need the access the VPP as fast as possible you can access the registers directly. This avoids the call and ret overhead. First you have to wait until the chip is ready. Then you can send one command with parameters to the chip. The command/parameter combination is 16 bits wide. The VPP executes the command when the TB register part is written. So you need to write to the corresponding TA register first. The chip is busy until the command is finished, but you only need to check this before trying the next command. The following piece of code draws an A at the position R3/R4:


        ; position the cursor at the beginning of line R4
        mov     r0,#vpp_busy            ; busy flag at bit 7
.busy1  movx    a,@r0
        jb7     .busy1                  ; wait for mailbox ready
        mov     r1,#vpp_ta_cmd          ; command register
        mov     a,r4
        movx    @r1,a
        inc     r1
        mov     a,#plus_cmd_loady
        movx    @r1,a                   ; vpp_tb_cmd
        dec     r1

        ; position the cursor at column R3
.busy2  movx    a,@r0
        jb7     .busy2                  ; wait for mailbox ready
        mov     a,r3
        movx    @r1,a                   ; vpp_ta_cmd
        inc     r1
        mov     a,#plus_cmd_loadx
        movx    @r1,a                   ; vpp_tb_cmd

        ; write a white 'A'
.busy3  movx    a,@r0
        jb7     .busy3                  ; wait for mailbox ready
        mov     r1,#vpp_ta_wr           ; write to data register
        mov     a,#col_plus_white       ; attribute byte
        movx    @r1,a
        inc     r1
        mov     a,#041h                 ; char 'A'
        movx    @r1,a                   ; vpp_tb_wr
        dec     r1

Questions answered so far

Some things were still unclear, but with the help of René van den Enden and some more experimentations I can now answer them:

Is the VDC display really always in front or can the box mode be used to put it behind?

The VDC is always in front. VDC graphics outside box mode can be blanked if pin B of the cartridge is not grounded. To use this feature with o2em you have to put "OPNB" at 040Ch into bank 1.

Why is there 6 KByte RAM when only 4 KByte are necessary?

Only 4 KByte are used, two of the RAM chips are only used as 1 KByte chips. The reason is probably that 2 KByte SRAM chips are much more common than 1 KByte.

How does A in plusmode affect the interrupts?

It does not, it was a very stupid programming error on my side.