Tutorial 7: Smooth scrolling & multicolor images with text

In this tutorial, we’ll be doing some neat stuff that will impress even your corpulent aunt.

Here’s what we’ll be aiming for:

The interesting stuff we’re doing here is displaying text as well as a multi color image in bitmap mode. The trick is as follows

  1. Wait for the raster to hit line 0
  2. Make sure you are in bitmap multi color mode
  3. Let the image display, but for each raster line apply a smooth sine scrolling
  4. When hitting a specific rasterline at the bottom of the screen, switch graphics mode to standard text
  5. scroll the text between 0-7 pixels
  6. when hitting the bottom, revert to multi color mode.

As the multi color image is stored in bank 1 while the text character map is stored in bank 0, we also will be performing a bank switch when jumping between modes. Details details!


program Tutorial7;
var
	xscroll, x,y, val, i: byte;
	textshift, wobbleShift: byte;
	text: array[255] of byte;
	time: byte;
	colorIndex:byte;
	fade : array [16] of byte = (11,6,6,12,4,14,15,1,1,15,14,4,12,6,6,11); 
	
	mainChar: IncBin("test.bin","$27FF");
	image_color: IncBin("images/octopus_color.bin", "$5000");
	
	image_data: IncBin("images/octopus_data.bin", "$6000");

Nothing too surprising here. As in Tutorial 6, we include a multicolor image in memory bank 1, and have also added a color fade array.


procedure PrintText();
begin
	// move to screen position
	moveto(2,23, $04);
	// print text
	PrintString(text, textshift, 36);
	// move cursor to color
	moveto(2,23, $D8);
	colorIndex:=colorIndex+1;

	for x:=0 to 36 do begin
		val:=fade[((x+colorIndex)/2)&15];
		screenmemory[x]:=val;

	end;
end;
/pre>

This method just prints the scrolling text, with a shift given by the “textshift” parameter. In addition, we poke the color values shiftet by a sine function. Nice!


interrupt UpdateRaster();
begin
	// increase global time
	time:=time+1;
	// increase text shift only every 8th step due to scrolling 

	x:=time&7;
	if time&7=0 then begin
		textshift:=textshift+ 1;
	end;
	// increase scrolling 

	xscroll:=(xscroll+1)&7;
	y:=0;
	// Optional wobble effect on the main image	
	wobbleShift:=sine[time*2];
	while y<210 do begin
		// Keep until rasterline hits text line
		y:=peek(RASTERLINE_POS, 0);
		val:=sine[y*8 + wobbleShift]/32;
		scrollx(val);
		waitnoraster(1);
	end;

	// Wait for text line raster
	waitForRaster(23*10);
	// switch bank to 0
	setbank(VIC_BANK0);
	// switch graphics mode
	
	setregularcolormode();
	settextmode();
	// set the vic's data to point to the custom character set
	poke(VIC_DATA_LOC, 0, $1A);

	// scroll this area
	Scrollx(8-xscroll);
	// wait for rasterline to hit near bottom
	waitForRaster(25*10);
	// switch back to bank 1 and set multi color mode again

	setbank(VIC_BANK1);

	Scrollx(0); 
	setmulticolormode();
	setbitmapmode();

	// Make sure we point the vic to the bitmap data
	poke(VIC_DATA_LOC, 0, $18);
	// finally, update the text

	PrintText();
	// call system kernel
	kernalinterrupt();
end;

This is the main bulk. Breakdown:

  • Update timer, text scrolling index (0-7 pixels)  and text shift index (i.e. the current position in the text, which should be updated for every scrolling index=0)
  • Add a wobble effect to the main image that is currently displayed: while the current rasterline is *above* the line with the text,  set the x scroll register to some arbitrary sine value and wait yet another raster line.
  • When hitting the desired rasterline (here 230), perform the magic:
    • Switch VIC bank to bank 1, where the character map is stored
    • Change to regular text mode, non-multicolor
    • Set the character map's position
    • Set the text scroll x register
    • Wait until the rasterline leaves the desired area for text ( here, around 250)
  • Now revert back to multicolor bitmap mode, scrolling to zero etc
  • Print the updated text

The rest of the code (Setup and Main) should be quite self-explanatory. The important part is copying the image_color data to the Bank 1 of the VIC chip, which is performed with the "copyImageColorData" method.

procedure Setup();
procedure Setup();
begin
	ClearScreen($20, SCREEN_CHAR_LOC);
	Poke(SCREEN_BG_COL, 0, BLACK);
	Poke(SCREEN_FG_COL, 0, BLACK);

	setbank(VIC_BANK1);
	copyimagecolordata(image_color,1);

	text:="                WHY AM I DOING THIS WHEN I SHOULD BE SLEEPING        I WANT SMOOTH HARDWARE SCROLLING IRL                  THIS SCOLLING DOESN'T END PROPERLY";
end;

begin
	Setup();

	DisableInterrupts();
	RasterIRQ(UpdateRaster(), 0);
	EnableInterrupts();

	Loop();

end.