Ciriciao folks!
This one needs some explanation, what is vcbase? According to the VIC-II article vc is an internal 10 bit counter register that is used to scan the 1000 cells of the screen,
vcbase is another register that is used to initialize vc after each scanline.
At the start of a frame vcbase is set to 0, so in text mode the screen starts with the first byte pointed by the video page in $18,
after each column vc is incremented, after each scanline vc is reset to vcbase if the row is not finished,
or the other way around vcbase is set to vc after one full row (8 scanlines).
So vcbase is 40 at the beginning of the second row (read byte with offset 40 of the video page),
80 for the next row, etc.
What if we could at the begininning of each frame set the value of vcbase to something else than 0?
What for?
One effect thet requires precise timing, also explained in the VIC-II Article, is called DMA Delay.
It is used to increment vc and vcbase before starting to show the screen,
thus scrolling it sideways of the desired amount of characters.
Vc and vcbase are 10 bit registers, so somewhere in the last part of the scrolled screen the counter wraps and the first bytes of the video page are displayed.
Contuining with the experiment of using adders where VIC-II used justaxpositions,
we'll extend vc and vcbase to 14 bits (no wrap-arounds until the end of the 16KB bank)
and add a new write-only register vcbase_latch.
In the previous post the adder was only 4 bits wide and did not give issues in VIC-II Kawari,
now vc is extended from 10 to 14 bits and the 4 additional bits overlap and need another 4 bit adder.
One other advantage of having 14 bits is that the screen can also be scrolled vertically of any amount of characters.
Mind that the color memory is still only 1K, so the counter will wrap at 10 bit boundaries for the colors, as bofore.
Implementation in Vice
No special flag to enable this feature, the Kernal initializes vcbase_latch to 0,
so everityhing works as before if you don't change it.
A new internal register is added in file vice/src/viciisc/viciitypes.h:
/* Internal memory pointer (VCBASE). */ int vcbase; int vcbase_latch;
In file vice/src/viciisc/vicii-mem.c write accesses to registers $1E and $1F are diverted to vcbase_latch:
inline static void vcbase_store(const uint16_t addr, const uint8_t value) { VICII_DEBUG_REGISTER(("WIV vc base register %s: $%02X", (addr == 0x1e) ? "LOW" : "HIGH", value)); if (addr == 0x1e) { ((uint8_t *)&vicii.vcbase_latch)[0] = value; } else { ((uint8_t *)&vicii.vcbase_latch)[1] = value & 0x3f; } } ... case 0x1e: /* $D01E: Sprite-sprite collision or VIC-WIV vc base low */ case 0x1f: /* $D01F: Sprite-background collision or VIC-WIV vc base high */ if (IS_WIV) { vcbase_store(addr, value); } else { collision_store(addr, value); }
In file vice/src/viciisc/vicii-cycle.c vcbase is initialized at the beggining of each frame to vcbase_latch:
vicii.vcbase = IS_WIV ? vicii.vcbase_latch : 0;
Implementation in VIC-II Kawari
In file hdl/matrix.v vcbase is initialized:
`ifdef WIV_EXTENSIONS vc_base <= wiv_vcbase_latch; vc <= wiv_vcbase_latch; `else vc_base <= 10'd0; vc <= 10'd0; `endif
And in file hdl/addressgen.v it's used for the bitmap mode, 11 bits now instead of the 10 bits of before:
if (wiv_xmp) vic_addr = {cb + vc[10:7], vc[6:0], rc}; // bitmap data else vic_addr = {cb[3] + vc[10], vc[9:0], rc}; // bitmap data
And for text mode, the whole 14 bits:
`ifdef WIV_EXTENSIONS vic_addr = {vm + vc[13:10], vc[9:0]}; // video matrix c-access `else vic_addr = {vm, vc}; // video matrix c-access `endif
BASIC example
Only one example in text mode, with increments or decrements of 1 you get an horizontal scrolling, with steps of 40 yuou get a vertical scrolling.
10 rem ** vertical scroll 20 for i=24 to 0 step -1 25 a=i*40 30 poke 53278,(a and 255) 35 poke 53279,(a / 256) 40 for p=0 to 200:next 45 next 50 rem ** horizontal scroll 60 for i=39 to 0 step -1 70 poke 53278,i 80 for p=0 to 200:next 85 next