2023-01-24

What if VIC-II had no borders

Ciriciao folks!
Let's start doing real juicy modifications with an easy one, that fully illustrates my thoughts.

When I think to what Commodore could have done differently with the graphics processor of the Commodore 64 I'm not thinking to complete redesigns of the chip (at least not initially), but to small changes that could have been introduced without altering the complexity or the cost of the VIC-II.
I'm not even thinking to something new, but something that existed in graphics chips from competitors or previous products of Commodore, such as the VIC chip (the graphics processor of the VIC 20).

For instance VIC could display a variable size video matrix, the default dimension was 22 columns by 23 rows, but that could be changed programmatically. VIC-II can not, the video matrix is hardwired to 40x25.
VIC could move the video matrix to some extent by many characters, VIC-II can only move it by 7 pixels.
VIC could produce an interlaced video signal (only in NTSC), VIC-II can not.

It must be said that with clever programming some of the VIC-II limitations can be overtaken, but at the expense of the CPU spending some or most of its time mangling with VIC-II registers.
One such trick is what the VIC-II article calls the hyperscreen, commonly named "opening the borders".

Why the VIC-II has borders and why programmers want to remove them?

One reason to have borders is to mask out parts of sprites when they move in or out of the sides of the screen, one reason not to have borders is to see sprites when they are out of the screen!
This is often used in games to display score and other information in the upper or lower borders, because opening the upper/lower border is relatively easy. Opening the left/right border on the other hand is trickier and consumes a lot of CPU time.

So what if VIC-II had two flags in his registers to programmatically disable the upper/lower borders or the left/right borders?

For reasons that are explaned in the VIC-II Article and are reflected in VICE sources, one flag named DVB will disable the vertical border, but the other named DMB (Disable Main Border) will disable both vertical and horizontal borders. Sorry, no flag for disabling only the horizontal border.
There is a difference though in disabling only the main border or disabling both: the idle pattern is shown in the vertical border only when DVB is set.

Implementation in Vice

Two new macros to query the value of the new flags are added in file vice/src/viciisc/viciitypes.h

/* VIC-II WIV flags */
#define WIV_CRE (vicii.regs[0x13] & 0x01) /* Control Registers Enable: reads to $13 and $14 give control registers instead of light pen position */
#define WIV_DVB (vicii.regs[0x13] & 0x04) /* Disable Vertical Border */
#define WIV_DMB (vicii.regs[0x13] & 0x08) /* Disable Main Border */

The macros are used in file vice/src/viciisc/vicii-cycle.c where the internal status of border unit is changed:

    if (line == (rsel ? VICII_25ROW_STOP_LINE : VICII_24ROW_STOP_LINE)) {
        vicii.set_vborder = IS_WIV && WIV_DVB ? 0 : 1;
    }
...
    /* Right border starts at cycles 56 (csel=0) or 57 (csel=1) on PAL. */
    if (cycle_is_check_border_r(cycle_flags, csel)) {
        vicii.main_border = IS_WIV && WIV_DMB ? 0 : 1;
    }

Implementation in VIC-II Kawari

Two flags are added to the CR3 register in file hdl/registers.v:

           output reg wiv_cre = 1'b0, // VIC-WIV control registers read enable
           output reg wiv_dvb = 1'b0, // VIC-WIV disable vertical border
           output reg wiv_dmb = 1'b0, // VIC-WIV disable main border

That can be read:

                    /* 0x13 */ `REG_LIGHT_PEN_X: begin
                        if (wiv_cre) begin
                            dbo[0] <= wiv_cre;
                            dbo[2] <= wiv_dvb;
                            dbo[3] <= wiv_dmb;
                        end else begin

and written:

                    /* 0x13 */ `REG_LIGHT_PEN_X: begin
                        wiv_cre <= dbi[0];
                        wiv_dvb <= dbi[2];
                        wiv_dmb <= dbi[3];
                    end

The new flags are outputs of the registers module and inputs of the border module, file hdl/border.v

`ifdef WIV_EXTENSIONS
           input wiv_dvb, // VIC-WIV disable vertical border
           input wiv_dmb, // VIC-WIV disable main border
`endif

They are used to disable the vertical border:

`ifdef WIV_EXTENSIONS
                set_vborder = ~wiv_dvb;
`else
                set_vborder = 1;
`endif

and disable the main border:

`ifdef WIV_EXTENSIONS
            main_border = ~wiv_dmb;
`else
            main_border = 1;
`endif

This is almost the same as in Vice!

Flags travelling from one component to another need 'wires' declared in hdl/vicii.v:

`ifdef WIV_EXTENSIONS
wire wiv_cre; // VIC-WIV control registers read enable
wire wiv_dvb; // VIC-WIV disable vertical border
wire wiv_dmb; // VIC-WIV disable main border
`endif

and wires are connected to the components later in the same file:

border vic_border(
           ...
`ifdef WIV_EXTENSIONS
           .wiv_dvb(wiv_dvb),
           .wiv_dmb(wiv_dmb),
`endif
           ...
       );
registers vic_registers(
              ...
`ifdef WIV_EXTENSIONS
              .wiv_cre(wiv_cre),
              .wiv_dvb(wiv_dvb),
              .wiv_dmb(wiv_dmb),
`endif
              ...
          );

And that's all, who thought that making a modification to a chip would have been so easy!

BASIC example

Display sprites in the border from a BASIC program, yay!

10 rem * pattern under vertical border
20 poke 16383,34
30 rem * square sprites under borders
40 for i=0to62:poke 16320+i,255:next
50 for i=0to7:poke 2040+i,255:next
60 poke 53269,255:poke 53264,12
70 poke 53248,100:poke 53249,25
71 poke 53250,150:poke 53251,25
72 poke 53252,90 :poke 53253,50
73 poke 53254,90 :poke 53255,100
74 poke 53256,200:poke 53257,255
75 poke 53258,250:poke 53259,255
76 poke 53260,0  :poke 53261,150
77 poke 53262,0  :poke 53263,200
110 poke 53267,0
120 print"full borders"
130 input a$
140 poke 53267,4
150 print"no vertical border"
160 input a$
170 poke 53267,8
180 print"no main border"
190 input a$
200 poke 53267,12
210 print"both disabled"
220 input a$
230 goto 110

Output:

output

No comments:

Post a Comment