Added comments to source samples
This commit is contained in:
parent
b9a1689dc6
commit
2d0f20cadc
|
@ -320,6 +320,7 @@ void rirq_sort(void)
|
||||||
rasterIRQNext[i] = rasterIRQRows[rasterIRQIndex[i]];
|
rasterIRQNext[i] = rasterIRQRows[rasterIRQIndex[i]];
|
||||||
|
|
||||||
npos++;
|
npos++;
|
||||||
|
vic.raster = rasterIRQNext[nextIRQ] - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rirq_start(void)
|
void rirq_start(void)
|
||||||
|
|
|
@ -3,29 +3,38 @@
|
||||||
#include <c64/memmap.h>
|
#include <c64/memmap.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
|
||||||
|
// Address of hires buffer and color buffer
|
||||||
#define Screen ((char *)0xe000)
|
#define Screen ((char *)0xe000)
|
||||||
#define Color ((char *)0xc800)
|
#define Color ((char *)0xc800)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Install the IRQ trampoline
|
||||||
mmap_trampoline();
|
mmap_trampoline();
|
||||||
|
|
||||||
|
// Turn of the kernal ROM
|
||||||
mmap_set(MMAP_NO_ROM);
|
mmap_set(MMAP_NO_ROM);
|
||||||
|
|
||||||
|
// Switch VIC into hires mode
|
||||||
vic_setmode(VICM_HIRES, Color, Screen);
|
vic_setmode(VICM_HIRES, Color, Screen);
|
||||||
|
|
||||||
|
// Clear the screen
|
||||||
memset(Screen, 0, 8000);
|
memset(Screen, 0, 8000);
|
||||||
memset(Color, 0x10, 1000);
|
memset(Color, 0x10, 1000);
|
||||||
|
|
||||||
|
// Loop over all pixels
|
||||||
int py, px;
|
int py, px;
|
||||||
|
|
||||||
for(py=0; py<200; py++)
|
for(py=0; py<200; py++)
|
||||||
{
|
{
|
||||||
for(px=0; px<320; px++)
|
for(px=0; px<320; px++)
|
||||||
{
|
{
|
||||||
|
// Value in the complex plane
|
||||||
|
|
||||||
float xz = (float)px * (3.5 / 320.0)- 2.5;
|
float xz = (float)px * (3.5 / 320.0)- 2.5;
|
||||||
float yz = (float)py * (2.0 / 200.0) - 1.0;
|
float yz = (float)py * (2.0 / 200.0) - 1.0;
|
||||||
|
|
||||||
|
// Iterate up to 32 times
|
||||||
float x = 0.0, y = 0.0;
|
float x = 0.0, y = 0.0;
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<32; i++)
|
for(i=0; i<32; i++)
|
||||||
|
@ -37,15 +46,19 @@ int main(void)
|
||||||
x = xt;
|
x = xt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a pixel if exceeds bound in less than 32 iterations
|
||||||
if (i < 32)
|
if (i < 32)
|
||||||
Screen[320 * (py >> 3) + (py & 7) + (px & ~7)] |= 0x80 >> (px & 7);
|
Screen[320 * (py >> 3) + (py & 7) + (px & ~7)] |= 0x80 >> (px & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-enable the kernal
|
||||||
mmap_set(MMAP_NO_BASIC);
|
mmap_set(MMAP_NO_BASIC);
|
||||||
|
|
||||||
|
// Wait for key press
|
||||||
getch();
|
getch();
|
||||||
|
|
||||||
|
// Restore VIC state
|
||||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
#include <c64/memmap.h>
|
#include <c64/memmap.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
|
||||||
|
// Address of hires buffer and color buffers
|
||||||
#define Screen ((char *)0xe000)
|
#define Screen ((char *)0xe000)
|
||||||
#define Color ((char *)0xc800)
|
#define Color ((char *)0xc800)
|
||||||
#define Color2 ((char *)0xd800)
|
#define Color2 ((char *)0xd800)
|
||||||
|
|
||||||
|
// Bit patters for eight different color pairs
|
||||||
char colors[] = {
|
char colors[] = {
|
||||||
0xff, 0xff,
|
0xff, 0xff,
|
||||||
0xee, 0xbb,
|
0xee, 0xbb,
|
||||||
|
@ -21,27 +23,35 @@ char colors[] = {
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Install the IRQ trampoline
|
||||||
mmap_trampoline();
|
mmap_trampoline();
|
||||||
|
|
||||||
|
// Turn of the kernal ROM
|
||||||
mmap_set(MMAP_NO_ROM);
|
mmap_set(MMAP_NO_ROM);
|
||||||
|
|
||||||
|
// Switch VIC into multicolor bitmap mode
|
||||||
vic_setmode(VICM_HIRES_MC, Color, Screen);
|
vic_setmode(VICM_HIRES_MC, Color, Screen);
|
||||||
|
|
||||||
|
// Clear the screen and set the colors
|
||||||
vic.color_back = 0x00;
|
vic.color_back = 0x00;
|
||||||
|
|
||||||
memset(Screen, 0, 8000);
|
memset(Screen, 0, 8000);
|
||||||
memset(Color, 0x27, 1000);
|
memset(Color, 0x27, 1000);
|
||||||
memset(Color2, 0x03, 1000);
|
memset(Color2, 0x03, 1000);
|
||||||
|
|
||||||
|
// Loop over all pixels
|
||||||
int py, px;
|
int py, px;
|
||||||
|
|
||||||
for(py=0; py<100; py++)
|
for(py=0; py<100; py++)
|
||||||
{
|
{
|
||||||
for(px=0; px<160; px++)
|
for(px=0; px<160; px++)
|
||||||
{
|
{
|
||||||
|
// Value in the complex plane
|
||||||
|
|
||||||
float xz = (float)px * (3.5 / 160.0)- 2.5;
|
float xz = (float)px * (3.5 / 160.0)- 2.5;
|
||||||
float yz = (float)py * (2.4 / 100.0) - 1.2;
|
float yz = (float)py * (2.4 / 100.0) - 1.2;
|
||||||
|
|
||||||
|
// Iterate up to 32 times
|
||||||
float x = 0.0, y = 0.0;
|
float x = 0.0, y = 0.0;
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<32; i++)
|
for(i=0; i<32; i++)
|
||||||
|
@ -55,20 +65,29 @@ int main(void)
|
||||||
|
|
||||||
if (i < 32)
|
if (i < 32)
|
||||||
{
|
{
|
||||||
|
// Position on screen
|
||||||
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (px & ~3);
|
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (px & ~3);
|
||||||
|
|
||||||
|
// Mask of pixels to change
|
||||||
char mask = 0xc0 >> (2 * (px & 3));
|
char mask = 0xc0 >> (2 * (px & 3));
|
||||||
|
|
||||||
|
// Get the two color patterns for upper and lower half
|
||||||
char c0 = colors[2 * (i & 7)], c1 = colors[2 * (i & 7) + 1];
|
char c0 = colors[2 * (i & 7)], c1 = colors[2 * (i & 7) + 1];
|
||||||
|
|
||||||
|
// Put the pixels into the image
|
||||||
dp[0] |= c0 & mask;
|
dp[0] |= c0 & mask;
|
||||||
dp[1] |= c1 & mask;
|
dp[1] |= c1 & mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-enable the kernal
|
||||||
mmap_set(MMAP_NO_BASIC);
|
mmap_set(MMAP_NO_BASIC);
|
||||||
|
|
||||||
|
// Wait for key press
|
||||||
getch();
|
getch();
|
||||||
|
|
||||||
|
// Restore VIC state
|
||||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
// Address of hires buffer and color buffers
|
||||||
#define Screen ((char *)0xe000)
|
#define Screen ((char *)0xe000)
|
||||||
#define Color1 ((char *)0xc800)
|
#define Color1 ((char *)0xc800)
|
||||||
#define Color2 ((char *)0xd800)
|
#define Color2 ((char *)0xd800)
|
||||||
|
|
||||||
|
// Bit patters for two different color pairs and eight shades
|
||||||
byte colors[2][17] =
|
byte colors[2][17] =
|
||||||
{
|
{
|
||||||
{0x00,
|
{0x00,
|
||||||
|
@ -20,27 +22,37 @@ byte colors[2][17] =
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fill a vertical line x from py to ty with color c
|
||||||
void VLine(int x, int py, int ty, char c)
|
void VLine(int x, int py, int ty, char c)
|
||||||
{
|
{
|
||||||
|
// Clip boundaries
|
||||||
if (py < 0)
|
if (py < 0)
|
||||||
py = 0;
|
py = 0;
|
||||||
if (ty > 100)
|
if (ty > 100)
|
||||||
ty = 100;
|
ty = 100;
|
||||||
|
|
||||||
|
// Check if there are pixel to draw
|
||||||
if (py < ty)
|
if (py < ty)
|
||||||
{
|
{
|
||||||
|
// Calculate top address and mask
|
||||||
char mask = 0xc0 >> (2 * (x & 3));
|
char mask = 0xc0 >> (2 * (x & 3));
|
||||||
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (x & ~3);
|
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (x & ~3);
|
||||||
|
|
||||||
|
// Get the two color patterns
|
||||||
char c0 = colors[0][c] & mask, c1 = colors[1][c] & mask;
|
char c0 = colors[0][c] & mask, c1 = colors[1][c] & mask;
|
||||||
|
|
||||||
|
// Invert mask to cover the unchanged portion
|
||||||
mask = ~mask;
|
mask = ~mask;
|
||||||
|
|
||||||
|
// Loop over all pixels
|
||||||
char h = ty - py;
|
char h = ty - py;
|
||||||
while (h)
|
while (h)
|
||||||
{
|
{
|
||||||
|
// Apply color to memory
|
||||||
dp[0] = (dp[0] & mask) | c0;
|
dp[0] = (dp[0] & mask) | c0;
|
||||||
dp[1] = (dp[1] & mask) | c1;
|
dp[1] = (dp[1] & mask) | c1;
|
||||||
|
|
||||||
|
// Two pixel lines down
|
||||||
dp += 2;
|
dp += 2;
|
||||||
if (!((int)dp & 7))
|
if (!((int)dp & 7))
|
||||||
dp += 312;
|
dp += 312;
|
||||||
|
@ -50,6 +62,7 @@ void VLine(int x, int py, int ty, char c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate up to 32 iterations and return a smoothed height
|
||||||
float iter(float xz, float yz)
|
float iter(float xz, float yz)
|
||||||
{
|
{
|
||||||
float x = 0.0, y = 0.0, r;
|
float x = 0.0, y = 0.0, r;
|
||||||
|
@ -71,6 +84,7 @@ float iter(float xz, float yz)
|
||||||
return i - log(log(r)/log(64.0))/log(2.0)
|
return i - log(log(r)/log(64.0))/log(2.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate light with given new and old heights
|
||||||
int light(float hl, float hu, float h)
|
int light(float hl, float hu, float h)
|
||||||
{
|
{
|
||||||
float dx = h - hl, dz = h - hu, dy = 0.1;
|
float dx = h - hl, dz = h - hu, dy = 0.1;
|
||||||
|
@ -84,12 +98,16 @@ int light(float hl, float hu, float h)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Install the IRQ trampoline
|
||||||
mmap_trampoline();
|
mmap_trampoline();
|
||||||
|
|
||||||
|
// Turn of the kernal ROM
|
||||||
mmap_set(MMAP_NO_ROM);
|
mmap_set(MMAP_NO_ROM);
|
||||||
|
|
||||||
|
// Switch VIC into multicolor bitmap mode
|
||||||
vic_setmode(VICM_HIRES_MC, Color1, Screen);
|
vic_setmode(VICM_HIRES_MC, Color1, Screen);
|
||||||
|
|
||||||
|
// Clear the screen and set the colors
|
||||||
vic.color_back = 0x00;
|
vic.color_back = 0x00;
|
||||||
vic.color_border = 0x00;
|
vic.color_border = 0x00;
|
||||||
|
|
||||||
|
@ -97,22 +115,28 @@ int main(void)
|
||||||
memset(Color1, 0x26, 1000);
|
memset(Color1, 0x26, 1000);
|
||||||
memset(Color2, 0x0f, 1000);
|
memset(Color2, 0x0f, 1000);
|
||||||
|
|
||||||
|
// Height of previous row, needed for lighting
|
||||||
float hl[200];
|
float hl[200];
|
||||||
|
|
||||||
|
// Rotation of complex plane
|
||||||
float w = -0.7;
|
float w = -0.7;
|
||||||
float co = cos(w), si = sin(w);
|
float co = cos(w), si = sin(w);
|
||||||
|
|
||||||
|
// Loop from left to right
|
||||||
for(int x=-1; x<160; x+= 1)
|
for(int x=-1; x<160; x+= 1)
|
||||||
{
|
{
|
||||||
|
// Loop from far to nead
|
||||||
int py = 20;
|
int py = 20;
|
||||||
float hu = 0;
|
float hu = 0;
|
||||||
for(int y=1; y<200; y+= 1)
|
for(int y=1; y<200; y+= 1)
|
||||||
{
|
{
|
||||||
|
// Inverse 3D projection
|
||||||
float fz = 2.0 / (float)y;
|
float fz = 2.0 / (float)y;
|
||||||
float fx = (float)(x - 80) * fz / 100.0;
|
float fx = (float)(x - 80) * fz / 100.0;
|
||||||
|
|
||||||
float mz = fz * 100.0 - 3.0, mx = fx * 100.0;
|
float mz = fz * 100.0 - 3.0, mx = fx * 100.0;
|
||||||
|
|
||||||
|
// Rotation of the plane
|
||||||
float rx = mx * co - mz * si, rz = mx * si + mz * co;
|
float rx = mx * co - mz * si, rz = mx * si + mz * co;
|
||||||
float dp = iter(rx, rz);
|
float dp = iter(rx, rz);
|
||||||
float v = 2 * dp;
|
float v = 2 * dp;
|
||||||
|
@ -120,20 +144,25 @@ int main(void)
|
||||||
|
|
||||||
float fy = 5.0 * pow(2.0, - v * 0.4);
|
float fy = 5.0 * pow(2.0, - v * 0.4);
|
||||||
|
|
||||||
|
// Calculate light
|
||||||
int ni = light(hl[y], hu, fy);
|
int ni = light(hl[y], hu, fy);
|
||||||
|
|
||||||
|
// Update left column
|
||||||
hl[y] = fy;
|
hl[y] = fy;
|
||||||
hu = fy;
|
hu = fy;
|
||||||
|
|
||||||
|
// Forward 3D projection
|
||||||
int ty = 20 + y / 2 + (int)(floor(fy / fz));
|
int ty = 20 + y / 2 + (int)(floor(fy / fz));
|
||||||
|
|
||||||
int c;
|
|
||||||
|
|
||||||
|
// color of pixel
|
||||||
|
int c;
|
||||||
if (dp != 32)
|
if (dp != 32)
|
||||||
c = 1 + ni + 8 * ((int)floor(dp) & 1);
|
c = 1 + ni + 8 * ((int)floor(dp) & 1);
|
||||||
else
|
else
|
||||||
c = 0;
|
c = 0;
|
||||||
|
|
||||||
|
// Draw line if not dummy left row
|
||||||
if (x >= 0)
|
if (x >= 0)
|
||||||
VLine(x, py, ty, c);
|
VLine(x, py, ty, c);
|
||||||
|
|
||||||
|
@ -141,10 +170,13 @@ int main(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-enable the kernal
|
||||||
mmap_set(MMAP_NO_BASIC);
|
mmap_set(MMAP_NO_BASIC);
|
||||||
|
|
||||||
|
// Wait for key press
|
||||||
getch();
|
getch();
|
||||||
|
|
||||||
|
// Restore VIC state
|
||||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -3,18 +3,24 @@
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Set name for file and open it on drive 9
|
||||||
krnio_setnam("@0:CHARS,P,R");
|
krnio_setnam("@0:CHARS,P,R");
|
||||||
if (krnio_open(2, 9, 2))
|
if (krnio_open(2, 9, 2))
|
||||||
{
|
{
|
||||||
|
// Read bytes until failure
|
||||||
int ch, k = 0;
|
int ch, k = 0;
|
||||||
while ((ch = krnio_getch(2)) >= 0)
|
while ((ch = krnio_getch(2)) >= 0)
|
||||||
{
|
{
|
||||||
|
// Print the value of the byte
|
||||||
printf("%d : %d\n", k, ch)
|
printf("%d : %d\n", k, ch)
|
||||||
k++;
|
k++;
|
||||||
|
|
||||||
|
// Exit the loop if this was the last byte of the file
|
||||||
if (ch & 0x100)
|
if (ch & 0x100)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the file
|
||||||
krnio_close(2);
|
krnio_close(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,18 @@
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Set name for file and open it with replace on drive 9
|
||||||
krnio_setnam("@0:CHARS,P,W");
|
krnio_setnam("@0:CHARS,P,W");
|
||||||
if (krnio_open(2, 9, 2))
|
if (krnio_open(2, 9, 2))
|
||||||
{
|
{
|
||||||
|
// Write 128 bytes to the file, it would be more efficient
|
||||||
|
// to set the output channel with krnio_chkout() for the file and
|
||||||
|
// write the bytes using krnio_chrout()
|
||||||
|
|
||||||
for(char i=0; i<128; i++)
|
for(char i=0; i<128; i++)
|
||||||
krnio_putch(2, i);
|
krnio_putch(2, i);
|
||||||
|
|
||||||
|
// Close the file again
|
||||||
krnio_close(2);
|
krnio_close(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,18 @@ Score score[4];
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Set name for file and open it on drive 9
|
||||||
krnio_setnam("HIGHSCORE,P,R");
|
krnio_setnam("HIGHSCORE,P,R");
|
||||||
if (krnio_open(2, 9, 2))
|
if (krnio_open(2, 9, 2))
|
||||||
{
|
{
|
||||||
|
// Read the content of the file into the score arrayx
|
||||||
krnio_read(2, (char*)score, sizeof(score));
|
krnio_read(2, (char*)score, sizeof(score));
|
||||||
|
|
||||||
|
// Close the file
|
||||||
krnio_close(2);
|
krnio_close(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print the result to stdout
|
||||||
for(int i=0; i<4; i++)
|
for(int i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
printf("%s : %u\n", score[i].name, score[i].score);
|
printf("%s : %u\n", score[i].name, score[i].score);
|
||||||
|
|
|
@ -16,11 +16,14 @@ Score score[] = {
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Set name for file and open it with replace on drive 9
|
||||||
krnio_setnam("@0:HIGHSCORE,P,W");
|
krnio_setnam("@0:HIGHSCORE,P,W");
|
||||||
if (krnio_open(2, 9, 2))
|
if (krnio_open(2, 9, 2))
|
||||||
{
|
{
|
||||||
|
// Fill the file with the score array
|
||||||
krnio_write(2, (char*)score, sizeof(score));
|
krnio_write(2, (char*)score, sizeof(score));
|
||||||
|
|
||||||
|
// Close the file
|
||||||
krnio_close(2);
|
krnio_close(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,27 +12,40 @@ Bitmap Screen;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Install the IRQ trampoline
|
||||||
mmap_trampoline();
|
mmap_trampoline();
|
||||||
|
|
||||||
|
// Initialize the display bitmap
|
||||||
bm_init(&Screen, ScreenMem, 40, 25);
|
bm_init(&Screen, ScreenMem, 40, 25);
|
||||||
|
|
||||||
|
// Clear the color memory with ROM and IO disabled
|
||||||
mmap_set(MMAP_RAM);
|
mmap_set(MMAP_RAM);
|
||||||
memset(ScreenMem, 0, 8000);
|
memset(ScreenMem, 0, 8000);
|
||||||
memset(ColorMem, 0x70, 1000);
|
memset(ColorMem, 0x70, 1000);
|
||||||
mmap_set(MMAP_NO_ROM);
|
mmap_set(MMAP_NO_ROM);
|
||||||
|
|
||||||
|
// Switch VIC to hires mode
|
||||||
vic_setmode(VICM_HIRES, ColorMem, ScreenMem);
|
vic_setmode(VICM_HIRES, ColorMem, ScreenMem);
|
||||||
|
|
||||||
|
// Reenable the kernal rom
|
||||||
mmap_set(MMAP_ROM);
|
mmap_set(MMAP_ROM);
|
||||||
|
|
||||||
|
|
||||||
|
// Set name for file and open it with replace on drive 9
|
||||||
krnio_setnam("TESTIMAGE,P,R");
|
krnio_setnam("TESTIMAGE,P,R");
|
||||||
if (krnio_open(2, 9, 2))
|
if (krnio_open(2, 9, 2))
|
||||||
{
|
{
|
||||||
|
// Read the bitmap image in one go
|
||||||
krnio_read(2, ScreenMem, 8000);
|
krnio_read(2, ScreenMem, 8000);
|
||||||
|
|
||||||
|
// Close the file
|
||||||
krnio_close(2);
|
krnio_close(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for a character
|
||||||
getchar();
|
getchar();
|
||||||
|
|
||||||
|
// Restore VIC
|
||||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -13,27 +13,34 @@ char Buffer[200];
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Install the IRQ trampoline
|
||||||
mmap_trampoline();
|
mmap_trampoline();
|
||||||
|
|
||||||
|
// Initialize the display bitmap and a brush
|
||||||
bm_init(&Screen, ScreenMem, 40, 25);
|
bm_init(&Screen, ScreenMem, 40, 25);
|
||||||
bm_alloc(&Brush, 2, 2);
|
bm_alloc(&Brush, 2, 2);
|
||||||
|
|
||||||
|
// Clear the color memory with ROM and IO disabled
|
||||||
mmap_set(MMAP_RAM);
|
mmap_set(MMAP_RAM);
|
||||||
memset(ScreenMem, 0, 8000);
|
memset(ScreenMem, 0, 8000);
|
||||||
memset(ColorMem, 0x70, 1000);
|
memset(ColorMem, 0x70, 1000);
|
||||||
mmap_set(MMAP_NO_ROM);
|
mmap_set(MMAP_NO_ROM);
|
||||||
|
|
||||||
|
// Switch VIC to hires mode
|
||||||
vic_setmode(VICM_HIRES, ColorMem, ScreenMem);
|
vic_setmode(VICM_HIRES, ColorMem, ScreenMem);
|
||||||
|
|
||||||
|
// Draw the brush
|
||||||
ClipRect crb = {0, 0, 16, 16};
|
ClipRect crb = {0, 0, 16, 16};
|
||||||
bm_fill(&Brush, 0);
|
bm_fill(&Brush, 0);
|
||||||
bm_circle_fill(&Brush, &crb, 7, 7, 6, NineShadesOfGrey[8]);
|
bm_circle_fill(&Brush, &crb, 7, 7, 6, NineShadesOfGrey[8]);
|
||||||
|
|
||||||
|
// Draw the main image
|
||||||
ClipRect crr = {0, 0, 320, 200};
|
ClipRect crr = {0, 0, 320, 200};
|
||||||
bm_circle_fill(&Screen, &crr, 160, 100, 90, NineShadesOfGrey[8]);
|
bm_circle_fill(&Screen, &crr, 160, 100, 90, NineShadesOfGrey[8]);
|
||||||
bm_circle_fill(&Screen, &crr, 120, 80, 20, NineShadesOfGrey[0]);
|
bm_circle_fill(&Screen, &crr, 120, 80, 20, NineShadesOfGrey[0]);
|
||||||
bm_circle_fill(&Screen, &crr, 200, 80, 20, NineShadesOfGrey[0]);
|
bm_circle_fill(&Screen, &crr, 200, 80, 20, NineShadesOfGrey[0]);
|
||||||
|
|
||||||
|
// And a smile
|
||||||
for(int x=-40; x<=40; x+=4)
|
for(int x=-40; x<=40; x+=4)
|
||||||
{
|
{
|
||||||
int y = bm_usqrt(50 * 50 - x * x);
|
int y = bm_usqrt(50 * 50 - x * x);
|
||||||
|
@ -41,22 +48,32 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reenable the kernal rom
|
||||||
mmap_set(MMAP_ROM);
|
mmap_set(MMAP_ROM);
|
||||||
|
|
||||||
|
// Set name for file and open it with replace on drive 9
|
||||||
krnio_setnam("@0:TESTIMAGE,P,W");
|
krnio_setnam("@0:TESTIMAGE,P,W");
|
||||||
if (krnio_open(2, 9, 2))
|
if (krnio_open(2, 9, 2))
|
||||||
{
|
{
|
||||||
|
// Loop in chunks of 200 bytes
|
||||||
for(int i=0; i<8000; i+=200)
|
for(int i=0; i<8000; i+=200)
|
||||||
{
|
{
|
||||||
|
// Disable ROM
|
||||||
mmap_set(MMAP_NO_ROM);
|
mmap_set(MMAP_NO_ROM);
|
||||||
|
// Copy chunk into buffer
|
||||||
memcpy(Buffer, ScreenMem + i, 200);
|
memcpy(Buffer, ScreenMem + i, 200);
|
||||||
|
// Reeable the ROM
|
||||||
mmap_set(MMAP_ROM);
|
mmap_set(MMAP_ROM);
|
||||||
|
|
||||||
|
// Write the chunk to disk
|
||||||
krnio_write(2, Buffer, 200);
|
krnio_write(2, Buffer, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the file
|
||||||
krnio_close(2);
|
krnio_close(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore the VIC
|
||||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,25 +2,31 @@
|
||||||
#include <c64/rasterirq.h>
|
#include <c64/rasterirq.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
|
||||||
|
// Prepare small 14 color bars and one IRQ for back to normal
|
||||||
RIRQCode bars[15];
|
RIRQCode bars[15];
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// initialize raster IRQ
|
||||||
rirq_init(true);
|
rirq_init(true);
|
||||||
|
|
||||||
for(int i=0; i<15; i++)
|
for(int i=0; i<15; i++)
|
||||||
{
|
{
|
||||||
|
// Build color change raster IRQ
|
||||||
rirq_build(bars + i, 2);
|
rirq_build(bars + i, 2);
|
||||||
|
// Change border color
|
||||||
rirq_write(bars + i, 0, &vic.color_border, i);
|
rirq_write(bars + i, 0, &vic.color_border, i);
|
||||||
|
// Change background color
|
||||||
rirq_write(bars + i, 1, &vic.color_back, i);
|
rirq_write(bars + i, 1, &vic.color_back, i);
|
||||||
|
// Place it on screen
|
||||||
rirq_set(i, 80 + 8 * i, bars + i);
|
rirq_set(i, 80 + 8 * i, bars + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort all raster IRQs
|
||||||
rirq_sort();
|
rirq_sort();
|
||||||
|
|
||||||
|
// Start raster IRQs
|
||||||
rirq_start();
|
rirq_start();
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
|
||||||
|
// Five raster IRQs for top and bottom of the two chasing bars, and the bottom
|
||||||
|
// of the screen
|
||||||
RIRQCode ftop, fbottom, btop, bbottom, final ;
|
RIRQCode ftop, fbottom, btop, bbottom, final ;
|
||||||
|
|
||||||
char sintab[256];
|
char sintab[256];
|
||||||
|
|
|
@ -8,26 +8,36 @@ char spdata[] = {
|
||||||
#embed "../resources/friendlybear.bin"
|
#embed "../resources/friendlybear.bin"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Raster IRQs for last line of screen and below
|
||||||
RIRQCode open, bottom;
|
RIRQCode open, bottom;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// initialize raster IRQ
|
||||||
rirq_init(true);
|
rirq_init(true);
|
||||||
|
|
||||||
|
// Build open border raster IRQ
|
||||||
rirq_build(&open, 1);
|
rirq_build(&open, 1);
|
||||||
|
// Reduce vertical screen size to fool VIC counter
|
||||||
rirq_write(&open, 0, &vic.ctrl1, VIC_CTRL1_DEN | 3);
|
rirq_write(&open, 0, &vic.ctrl1, VIC_CTRL1_DEN | 3);
|
||||||
|
// Place it into the last line of the screen
|
||||||
rirq_set(0, 50 + 200 - 3, &open);
|
rirq_set(0, 50 + 200 - 3, &open);
|
||||||
|
|
||||||
|
// Build switch to normal raster IRQ
|
||||||
rirq_build(&bottom, 1);
|
rirq_build(&bottom, 1);
|
||||||
rirq_write(&bottom, 0, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3 );
|
rirq_write(&bottom, 0, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3 );
|
||||||
rirq_set(1, 50, &bottom);
|
rirq_set(1, 50, &bottom);
|
||||||
|
|
||||||
|
// sort the raster IRQs
|
||||||
rirq_sort();
|
rirq_sort();
|
||||||
|
|
||||||
|
// start raster IRQ processing
|
||||||
rirq_start();
|
rirq_start();
|
||||||
|
|
||||||
|
// Copy the sprite data
|
||||||
memcpy((char *)0x0380, spdata, 128);
|
memcpy((char *)0x0380, spdata, 128);
|
||||||
|
|
||||||
|
// Initialize sprites
|
||||||
*(char *)(0x7f8) = 0x03c0 / 64;
|
*(char *)(0x7f8) = 0x03c0 / 64;
|
||||||
*(char *)(0x7f9) = 0x0380 / 64;
|
*(char *)(0x7f9) = 0x0380 / 64;
|
||||||
*(char *)(0x7fa) = 0x03c0 / 64;
|
*(char *)(0x7fa) = 0x03c0 / 64;
|
||||||
|
@ -52,6 +62,7 @@ int main(void)
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Move sprites through all vertical positions
|
||||||
for(int i=0; i<255; i++)
|
for(int i=0; i<255; i++)
|
||||||
{
|
{
|
||||||
vic_sprxy(0, 100, 1 * i); vic_sprxy(1, 100, 1 * i);
|
vic_sprxy(0, 100, 1 * i); vic_sprxy(1, 100, 1 * i);
|
||||||
|
|
|
@ -10,29 +10,44 @@ const char * Text =
|
||||||
S"CORPORIS, EOS? UNDE VERO ISTE QUIA? EAQUE EAQUE. IN. AUT ID "
|
S"CORPORIS, EOS? UNDE VERO ISTE QUIA? EAQUE EAQUE. IN. AUT ID "
|
||||||
S"EXPEDITA ILLUM MOLESTIAS, ";
|
S"EXPEDITA ILLUM MOLESTIAS, ";
|
||||||
|
|
||||||
|
// Raster interrupt command structure for change to scrolled and back
|
||||||
|
|
||||||
RIRQCode scroll, bottom;
|
RIRQCode scroll, bottom;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// initialize raster IRQ
|
||||||
rirq_init(true);
|
rirq_init(true);
|
||||||
|
|
||||||
|
// Build switch to scroll line IRQ
|
||||||
rirq_build(&scroll, 1);
|
rirq_build(&scroll, 1);
|
||||||
|
// Change control register two with this IRQ
|
||||||
rirq_write(&scroll, 0, &vic.ctrl2, 0);
|
rirq_write(&scroll, 0, &vic.ctrl2, 0);
|
||||||
|
// Put it onto the scroll line
|
||||||
rirq_set(0, 50 + 24 * 8, &scroll);
|
rirq_set(0, 50 + 24 * 8, &scroll);
|
||||||
|
|
||||||
|
// Build the switch to normal IRQ
|
||||||
rirq_build(&bottom, 1);
|
rirq_build(&bottom, 1);
|
||||||
|
// re-enable left and right column and reset horizontal scroll
|
||||||
rirq_write(&bottom, 0, &vic.ctrl2, VIC_CTRL2_CSEL);
|
rirq_write(&bottom, 0, &vic.ctrl2, VIC_CTRL2_CSEL);
|
||||||
|
// place this at the bottom
|
||||||
rirq_set(1, 250, &bottom);
|
rirq_set(1, 250, &bottom);
|
||||||
|
|
||||||
|
// sort the raster IRQs
|
||||||
rirq_sort();
|
rirq_sort();
|
||||||
|
|
||||||
|
// start raster IRQ processing
|
||||||
rirq_start();
|
rirq_start();
|
||||||
|
|
||||||
|
// Loop through text
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// wait for raster reaching bottom of screen
|
||||||
rirq_wait();
|
rirq_wait();
|
||||||
|
// Update raster IRQ for scroll line with new horizontal scroll offset
|
||||||
rirq_data(&scroll, 0, 7 - (x & 7));
|
rirq_data(&scroll, 0, 7 - (x & 7));
|
||||||
|
// Copy scrolled version of text when switching over char border
|
||||||
if ((x & 7) == 0)
|
if ((x & 7) == 0)
|
||||||
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
|
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
|
||||||
x++;
|
x++;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
byte font[2048];
|
byte font[2048];
|
||||||
|
|
||||||
|
// Copy the system font into local RAM for easy access
|
||||||
void copyFont(void)
|
void copyFont(void)
|
||||||
{
|
{
|
||||||
mmap_set(MMAP_CHAR_ROM);
|
mmap_set(MMAP_CHAR_ROM);
|
||||||
|
@ -13,15 +14,23 @@ void copyFont(void)
|
||||||
mmap_set(MMAP_ROM);
|
mmap_set(MMAP_ROM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Screen and color space
|
||||||
#define screen ((byte *)0x0400)
|
#define screen ((byte *)0x0400)
|
||||||
#define color ((byte *)0xd800)
|
#define color ((byte *)0xd800)
|
||||||
|
|
||||||
|
// Macro for easy access to screen space
|
||||||
#define sline(x, y) (screen + 40 * (y) + (x))
|
#define sline(x, y) (screen + 40 * (y) + (x))
|
||||||
|
|
||||||
|
// Start row for text
|
||||||
#define srow 5
|
#define srow 5
|
||||||
|
|
||||||
|
// Move the screen one character to the left
|
||||||
void scrollLeft(void)
|
void scrollLeft(void)
|
||||||
{
|
{
|
||||||
|
// Loop horizontaly
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
{
|
{
|
||||||
|
// Unroll vetical loop 16 times
|
||||||
#assign y 0
|
#assign y 0
|
||||||
#repeat
|
#repeat
|
||||||
sline(0, srow + y)[x] = sline(1, srow + y)[x];
|
sline(0, srow + y)[x] = sline(1, srow + y)[x];
|
||||||
|
@ -30,10 +39,13 @@ void scrollLeft(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand one column of a glyph to the right most screen column
|
||||||
void expand(char c, byte f)
|
void expand(char c, byte f)
|
||||||
{
|
{
|
||||||
|
// Address of glyph data
|
||||||
byte * fp = font + 8 * c;
|
byte * fp = font + 8 * c;
|
||||||
|
|
||||||
|
// Unroll eight times for each byte in glyph data
|
||||||
#assign y 0
|
#assign y 0
|
||||||
#repeat
|
#repeat
|
||||||
sline(39, srow + 2 * y + 0)[0] =
|
sline(39, srow + 2 * y + 0)[0] =
|
||||||
|
@ -54,28 +66,36 @@ const char * text =
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Install the IRQ trampoline
|
||||||
mmap_trampoline();
|
mmap_trampoline();
|
||||||
|
|
||||||
|
// Copy the font data
|
||||||
copyFont();
|
copyFont();
|
||||||
|
|
||||||
|
// Cleat the screen
|
||||||
memset(screen, 0x20, 1000);
|
memset(screen, 0x20, 1000);
|
||||||
|
|
||||||
|
// Color bars
|
||||||
for(int i=0; i<16; i++)
|
for(int i=0; i<16; i++)
|
||||||
memset(color + 40 * (srow + i), i + 1, 40);
|
memset(color + 40 * (srow + i), i + 1, 40);
|
||||||
|
|
||||||
vic.color_back = VCOL_BLACK;
|
vic.color_back = VCOL_BLACK;
|
||||||
vic.color_border = VCOL_BLACK;
|
vic.color_border = VCOL_BLACK;
|
||||||
|
|
||||||
|
// Hide left and right column
|
||||||
vic.ctrl2 = 0;
|
vic.ctrl2 = 0;
|
||||||
|
|
||||||
|
// Loop over text
|
||||||
int ci = 0;
|
int ci = 0;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Loop over glyph from left to right
|
||||||
byte cf = 0x80;
|
byte cf = 0x80;
|
||||||
while (cf)
|
while (cf)
|
||||||
{
|
{
|
||||||
for(char i=0; i<2; i++)
|
for(char i=0; i<2; i++)
|
||||||
{
|
{
|
||||||
|
// Pixel level scrolling
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
vic.ctrl2 = 4;
|
vic.ctrl2 = 4;
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
|
@ -91,12 +111,16 @@ int main(void)
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
vic.ctrl2 = 6;
|
vic.ctrl2 = 6;
|
||||||
|
|
||||||
|
// Crossing character border, now scroll and show new column
|
||||||
scrollLeft();
|
scrollLeft();
|
||||||
expand(text[ci], cf);
|
expand(text[ci], cf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Next glyph column
|
||||||
cf >>= 1;
|
cf >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Next character
|
||||||
ci++;
|
ci++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
#include <c64/joystick.h>
|
#include <c64/joystick.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Screen and color space
|
||||||
#define Screen ((byte *)0x0400)
|
#define Screen ((byte *)0x0400)
|
||||||
#define Color ((byte *)0xd800)
|
#define Color ((byte *)0xd800)
|
||||||
|
|
||||||
|
// Macro for easy access to screen and color space
|
||||||
#define sline(x, y) (Screen + 40 * (y) + (x))
|
#define sline(x, y) (Screen + 40 * (y) + (x))
|
||||||
#define cline(x, y) (Color + 40 * (y) + (x))
|
#define cline(x, y) (Color + 40 * (y) + (x))
|
||||||
|
|
||||||
|
// Tile data, each column has four rows of four tiles
|
||||||
static const char quad[4][4 * 4] =
|
static const char quad[4][4 * 4] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -40,6 +44,7 @@ static const char quad[4][4 * 4] =
|
||||||
|
|
||||||
#pragma align(quad, 256)
|
#pragma align(quad, 256)
|
||||||
|
|
||||||
|
// Expand a single row into an offscreen buffer
|
||||||
void expandrow(char * dp, char * cp, const char * grid, char ly, char lx)
|
void expandrow(char * dp, char * cp, const char * grid, char ly, char lx)
|
||||||
{
|
{
|
||||||
char hx = 0;
|
char hx = 0;
|
||||||
|
@ -56,6 +61,7 @@ void expandrow(char * dp, char * cp, const char * grid, char ly, char lx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand a single column into an offscreen buffer
|
||||||
void expandcol(char * dp, char * cp, const char * grid, char ly, char lx)
|
void expandcol(char * dp, char * cp, const char * grid, char ly, char lx)
|
||||||
{
|
{
|
||||||
for(char y=0; y<25; y++)
|
for(char y=0; y<25; y++)
|
||||||
|
@ -71,25 +77,39 @@ void expandcol(char * dp, char * cp, const char * grid, char ly, char lx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Two split scroll for left, right and up
|
||||||
#define VSPLIT 12
|
#define VSPLIT 12
|
||||||
|
|
||||||
|
// Three split scroll for down. Downscrolling is more tricky because
|
||||||
|
// we have to copy towards the raster
|
||||||
#define VSPLIT 12
|
#define VSPLIT 12
|
||||||
#define VSPLIT2 20
|
#define VSPLIT2 20
|
||||||
|
|
||||||
|
// New line/column of screen and color data
|
||||||
char news[40], newc[40];
|
char news[40], newc[40];
|
||||||
|
|
||||||
|
// All scroll routines start with a pixel offset of 4, 4
|
||||||
|
|
||||||
|
// Scroll one character left in two pixel increments
|
||||||
void scroll_left(void)
|
void scroll_left(void)
|
||||||
{
|
{
|
||||||
|
// Wait for one frame
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Switch to offset 2, 4
|
||||||
vic.ctrl2 = 0x02;
|
vic.ctrl2 = 0x02;
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Switch to offset 0, 4
|
||||||
vic.ctrl2 = 0x00;
|
vic.ctrl2 = 0x00;
|
||||||
|
|
||||||
|
// Wait until bottom of section
|
||||||
vic_waitLine(50 + 8 * VSPLIT);
|
vic_waitLine(50 + 8 * VSPLIT);
|
||||||
|
|
||||||
|
// Scroll upper section
|
||||||
|
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
{
|
{
|
||||||
#assign ty 0
|
#assign ty 0
|
||||||
|
@ -100,6 +120,7 @@ void scroll_left(void)
|
||||||
#until ty == VSPLIT
|
#until ty == VSPLIT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update column
|
||||||
#assign ty 0
|
#assign ty 0
|
||||||
#repeat
|
#repeat
|
||||||
sline(0, ty)[39] = news[ty];
|
sline(0, ty)[39] = news[ty];
|
||||||
|
@ -107,9 +128,13 @@ void scroll_left(void)
|
||||||
#assign ty ty + 1
|
#assign ty ty + 1
|
||||||
#until ty == VSPLIT
|
#until ty == VSPLIT
|
||||||
|
|
||||||
|
// Wait for bottom of visible screen
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Switch to offset 6, 4
|
||||||
vic.ctrl2 = 0x06;
|
vic.ctrl2 = 0x06;
|
||||||
|
|
||||||
|
// Scroll lower part of the screen, while top is redrawn
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
{
|
{
|
||||||
#assign ty VSPLIT
|
#assign ty VSPLIT
|
||||||
|
@ -120,6 +145,7 @@ void scroll_left(void)
|
||||||
#until ty == 25
|
#until ty == 25
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update new column
|
||||||
#assign ty VSPLIT
|
#assign ty VSPLIT
|
||||||
#repeat
|
#repeat
|
||||||
sline(0, ty)[39] = news[ty];
|
sline(0, ty)[39] = news[ty];
|
||||||
|
@ -127,11 +153,16 @@ void scroll_left(void)
|
||||||
#assign ty ty + 1
|
#assign ty ty + 1
|
||||||
#until ty == 25
|
#until ty == 25
|
||||||
|
|
||||||
|
// Wait for bottom
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Now back to 4, 4
|
||||||
vic.ctrl2 = 0x04
|
vic.ctrl2 = 0x04
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll one character right in two pixel increments
|
||||||
|
|
||||||
void scroll_right(void)
|
void scroll_right(void)
|
||||||
{
|
{
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
|
@ -185,6 +216,8 @@ void scroll_right(void)
|
||||||
vic.ctrl2 = 0x04;
|
vic.ctrl2 = 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll one character up in two pixel increments
|
||||||
|
|
||||||
void scroll_up(void)
|
void scroll_up(void)
|
||||||
{
|
{
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
|
@ -229,20 +262,36 @@ void scroll_up(void)
|
||||||
|
|
||||||
char tmp0[40], tmp1[40], tmp2[40], tmp3[40];
|
char tmp0[40], tmp1[40], tmp2[40], tmp3[40];
|
||||||
|
|
||||||
|
// Scroll one character down in two pixel increments. This is more tricky than
|
||||||
|
// the other three cases, because we have to work towards the beam because
|
||||||
|
// we have to copy backwards in memory.
|
||||||
|
//
|
||||||
|
// The scroll is split into three sections, the seam rows are saved into
|
||||||
|
// intermediate arrays, so we can copy the top section first and the bottom
|
||||||
|
// section last, and stay ahead of the beam.
|
||||||
|
|
||||||
void scroll_down(void)
|
void scroll_down(void)
|
||||||
{
|
{
|
||||||
|
// Wait one frame
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Save seam lines
|
||||||
for(char x=0; x<40; x++)
|
for(char x=0; x<40; x++)
|
||||||
{
|
{
|
||||||
tmp0[x] = sline(0, VSPLIT)[x];
|
tmp0[x] = sline(0, VSPLIT)[x];
|
||||||
tmp1[x] = cline(0, VSPLIT)[x];
|
tmp1[x] = cline(0, VSPLIT)[x];
|
||||||
|
tmp2[x] = sline(0, VSPLIT2)[x];
|
||||||
|
tmp3[x] = cline(0, VSPLIT2)[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now switch to 4, 6
|
||||||
vic.ctrl1 = 0x06 | VIC_CTRL1_DEN;
|
vic.ctrl1 = 0x06 | VIC_CTRL1_DEN;
|
||||||
|
|
||||||
|
// Wait for bottom of top section
|
||||||
vic_waitLine(58 + 8 * VSPLIT);
|
vic_waitLine(58 + 8 * VSPLIT);
|
||||||
|
|
||||||
|
// Scroll top section down and copy new column
|
||||||
for(char x=0; x<40; x++)
|
for(char x=0; x<40; x++)
|
||||||
{
|
{
|
||||||
#assign ty VSPLIT
|
#assign ty VSPLIT
|
||||||
|
@ -257,12 +306,12 @@ void scroll_down(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// vic_waitBottom();
|
// vic_waitBottom();
|
||||||
|
// We have already reached the bottom, switch to 4, 0
|
||||||
vic.ctrl1 = 0x00 | VIC_CTRL1_DEN;
|
vic.ctrl1 = 0x00 | VIC_CTRL1_DEN;
|
||||||
|
|
||||||
|
// Copy the second section, update the seam line from the buffer
|
||||||
for(char x=0; x<40; x++)
|
for(char x=0; x<40; x++)
|
||||||
{
|
{
|
||||||
tmp2[x] = sline(0, VSPLIT2)[x];
|
|
||||||
tmp3[x] = cline(0, VSPLIT2)[x];
|
|
||||||
|
|
||||||
#assign ty VSPLIT2
|
#assign ty VSPLIT2
|
||||||
#repeat
|
#repeat
|
||||||
|
@ -275,6 +324,7 @@ void scroll_down(void)
|
||||||
cline(0, ty)[x] = tmp1[x];
|
cline(0, ty)[x] = tmp1[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy the third section, update the seam line from the buffer
|
||||||
for(char x=0; x<40; x++)
|
for(char x=0; x<40; x++)
|
||||||
{
|
{
|
||||||
#assign ty 24
|
#assign ty 24
|
||||||
|
@ -288,9 +338,11 @@ void scroll_down(void)
|
||||||
cline(0, ty)[x] = tmp3[x];
|
cline(0, ty)[x] = tmp3[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Switch to 4, 2
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
vic.ctrl1 = 0x02 | VIC_CTRL1_DEN;
|
vic.ctrl1 = 0x02 | VIC_CTRL1_DEN;
|
||||||
|
|
||||||
|
// Switch to 4, 4
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
vic.ctrl1 = 0x04 | VIC_CTRL1_DEN;
|
vic.ctrl1 = 0x04 | VIC_CTRL1_DEN;
|
||||||
|
@ -302,11 +354,13 @@ char grid[16][16];
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// We need some more accurate timing for this, so kill the kernal IRQ
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
sei
|
sei
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init the grid
|
||||||
for(char y=0; y<16; y++)
|
for(char y=0; y<16; y++)
|
||||||
{
|
{
|
||||||
for(char x=0; x<16; x++)
|
for(char x=0; x<16; x++)
|
||||||
|
@ -317,6 +371,7 @@ int main(void)
|
||||||
|
|
||||||
char gridX = 0, gridY = 0;
|
char gridX = 0, gridY = 0;
|
||||||
|
|
||||||
|
// Inital drwaing of the screen
|
||||||
char * dp = Screen, * cp = Color;
|
char * dp = Screen, * cp = Color;
|
||||||
for(char y=0; y<25; y++)
|
for(char y=0; y<25; y++)
|
||||||
{
|
{
|
||||||
|
@ -325,11 +380,18 @@ int main(void)
|
||||||
cp += 40;
|
cp += 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup initial scroll offset
|
||||||
|
|
||||||
|
vic.ctrl1 = 0x04 | VIC_CTRL1_DEN;
|
||||||
|
vic.ctrl2 = 0x04
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Check the joystick
|
||||||
joy_poll(1);
|
joy_poll(1);
|
||||||
if (joyx[1] == 1)
|
if (joyx[1] == 1)
|
||||||
{
|
{
|
||||||
|
// Move to the right
|
||||||
if (gridX < 24)
|
if (gridX < 24)
|
||||||
{
|
{
|
||||||
gridX++;
|
gridX++;
|
||||||
|
@ -339,6 +401,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
else if (joyx[1] == -1)
|
else if (joyx[1] == -1)
|
||||||
{
|
{
|
||||||
|
// Move to the left
|
||||||
if (gridX > 0)
|
if (gridX > 0)
|
||||||
{
|
{
|
||||||
gridX--;
|
gridX--;
|
||||||
|
@ -348,6 +411,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
else if (joyy[1] == 1)
|
else if (joyy[1] == 1)
|
||||||
{
|
{
|
||||||
|
// Move down
|
||||||
if (gridY < 39)
|
if (gridY < 39)
|
||||||
{
|
{
|
||||||
gridY++;
|
gridY++;
|
||||||
|
@ -357,6 +421,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
else if (joyy[1] == -1)
|
else if (joyy[1] == -1)
|
||||||
{
|
{
|
||||||
|
// Move up
|
||||||
if (gridY > 0)
|
if (gridY > 0)
|
||||||
{
|
{
|
||||||
gridY--;
|
gridY--;
|
||||||
|
|
|
@ -3,16 +3,22 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Screen and color space
|
||||||
#define screen ((byte *)0x0400)
|
#define screen ((byte *)0x0400)
|
||||||
#define color ((byte *)0xd800)
|
#define color ((byte *)0xd800)
|
||||||
|
|
||||||
|
// Macro for easy access to screen and color space
|
||||||
#define sline(x, y) (screen + 40 * (y) + (x))
|
#define sline(x, y) (screen + 40 * (y) + (x))
|
||||||
#define cline(x, y) (color + 40 * (y) + (x))
|
#define cline(x, y) (color + 40 * (y) + (x))
|
||||||
|
|
||||||
|
// Column buffer for one prepared column of screen and color data
|
||||||
char rbuff[25], cbuff[25];
|
char rbuff[25], cbuff[25];
|
||||||
|
|
||||||
|
// Split into three scrolling sections to race the beam
|
||||||
#define SPLIT1 8
|
#define SPLIT1 8
|
||||||
#define SPLIT2 16
|
#define SPLIT2 16
|
||||||
|
|
||||||
|
// Scroll top section
|
||||||
void scrollLeft0(void)
|
void scrollLeft0(void)
|
||||||
{
|
{
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
|
@ -32,6 +38,7 @@ void scrollLeft0(void)
|
||||||
#until y == SPLIT1
|
#until y == SPLIT1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll bottom two sections
|
||||||
void scrollLeft1(void)
|
void scrollLeft1(void)
|
||||||
{
|
{
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
|
@ -67,7 +74,7 @@ void scrollLeft1(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Prepare a new column with random data
|
||||||
void prepcol(void)
|
void prepcol(void)
|
||||||
{
|
{
|
||||||
for(char i=0; i<25; i++)
|
for(char i=0; i<25; i++)
|
||||||
|
@ -80,6 +87,7 @@ void prepcol(void)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Clear the screen
|
||||||
memset(screen, 0x20, 1000);
|
memset(screen, 0x20, 1000);
|
||||||
memset(color, 7, 1000);
|
memset(color, 7, 1000);
|
||||||
|
|
||||||
|
@ -90,24 +98,33 @@ int main(void)
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Advance one pixel
|
||||||
|
|
||||||
x = (x + 1) & 7;
|
x = (x + 1) & 7;
|
||||||
|
|
||||||
|
// If we will cross the character boundary, scroll the top section
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
|
// Wait for raster reaching bottom of first section
|
||||||
vic_waitLine(50 + 8 * SPLIT1);
|
vic_waitLine(50 + 8 * SPLIT1);
|
||||||
|
// Scroll first section
|
||||||
scrollLeft0();
|
scrollLeft0();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for bottom of screen
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Update the pixel offset
|
||||||
vic.ctrl2 = (7 - x) & 7;
|
vic.ctrl2 = (7 - x) & 7;
|
||||||
|
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
|
// Scroll the bottom section if needed
|
||||||
scrollLeft1();
|
scrollLeft1();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Update the new column somewhere in the middle of the character
|
||||||
if (x == 4)
|
if (x == 4)
|
||||||
prepcol();
|
prepcol();
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
|
|
|
@ -4,10 +4,14 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <c64/rasterirq.h>
|
#include <c64/rasterirq.h>
|
||||||
|
|
||||||
|
// Screen and color space
|
||||||
#define screen ((byte *)0x0400)
|
#define screen ((byte *)0x0400)
|
||||||
#define color ((byte *)0xd800)
|
#define color ((byte *)0xd800)
|
||||||
|
|
||||||
|
// Macro for easy access to screen space
|
||||||
#define sline(x, y) (screen + 40 * (y) + (x))
|
#define sline(x, y) (screen + 40 * (y) + (x))
|
||||||
|
|
||||||
|
// Tile data, each column has four rows of four tiles
|
||||||
static const char quad[4][4 * 4] =
|
static const char quad[4][4 * 4] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -38,9 +42,11 @@ static const char quad[4][4 * 4] =
|
||||||
|
|
||||||
#pragma align(quad, 256)
|
#pragma align(quad, 256)
|
||||||
|
|
||||||
|
// expand one row with column offset 0 into the grid
|
||||||
void expandrow0(char * dp, const char * grid, char ly)
|
void expandrow0(char * dp, const char * grid, char ly)
|
||||||
{
|
{
|
||||||
char gi;
|
char gi;
|
||||||
|
// unroll for each char in the row
|
||||||
#assign gx 0
|
#assign gx 0
|
||||||
#repeat
|
#repeat
|
||||||
gi = grid[gx] | ly;
|
gi = grid[gx] | ly;
|
||||||
|
@ -52,6 +58,8 @@ void expandrow0(char * dp, const char * grid, char ly)
|
||||||
#until gx == 10
|
#until gx == 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expand one row with column offset 1 into the grid, so three
|
||||||
|
// chars from the first tile and one char from the last
|
||||||
void expandrow1(char * dp, const char * grid, char ly)
|
void expandrow1(char * dp, const char * grid, char ly)
|
||||||
{
|
{
|
||||||
char gi;
|
char gi;
|
||||||
|
@ -72,6 +80,8 @@ void expandrow1(char * dp, const char * grid, char ly)
|
||||||
dp[39] = quad[0][gi];
|
dp[39] = quad[0][gi];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expand one row with column offset 2 into the grid, so two
|
||||||
|
// chars from the first tile and two chars from the last
|
||||||
void expandrow2(char * dp, const char * grid, char ly)
|
void expandrow2(char * dp, const char * grid, char ly)
|
||||||
{
|
{
|
||||||
char gi;
|
char gi;
|
||||||
|
@ -92,6 +102,8 @@ void expandrow2(char * dp, const char * grid, char ly)
|
||||||
dp[39] = quad[1][gi];
|
dp[39] = quad[1][gi];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expand one row with column offset 3 into the grid, so one
|
||||||
|
// char from the first tile and trhee chars from the last
|
||||||
void expandrow3(char * dp, const char * grid, char ly)
|
void expandrow3(char * dp, const char * grid, char ly)
|
||||||
{
|
{
|
||||||
char gi;
|
char gi;
|
||||||
|
@ -112,16 +124,24 @@ void expandrow3(char * dp, const char * grid, char ly)
|
||||||
dp[39] = quad[2][gi];
|
dp[39] = quad[2][gi];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expand the visibile portion of the screen at the
|
||||||
|
// given char offset into the tiles
|
||||||
void expand(char * dp, const char * grid, char px, char py)
|
void expand(char * dp, const char * grid, char px, char py)
|
||||||
{
|
{
|
||||||
|
// remainder of position, offset into the tile
|
||||||
char ry = 4 * (py & 3);
|
char ry = 4 * (py & 3);
|
||||||
char rx = px & 3;
|
char rx = px & 3;
|
||||||
|
|
||||||
|
// target screen position
|
||||||
char * cdp = dp;
|
char * cdp = dp;
|
||||||
const char * cgrid = grid + (px >> 2) + 16 * (py >> 2);
|
|
||||||
|
|
||||||
|
// pointer to grid offset for top lest tile visible
|
||||||
|
const char * cgrid = grid + (px >> 2) + 32 * (py >> 2);
|
||||||
|
|
||||||
|
// Loop over all visible screen rows
|
||||||
for(char gy=0; gy<20; gy++)
|
for(char gy=0; gy<20; gy++)
|
||||||
{
|
{
|
||||||
|
// Update based on row (could be unrolled for inner groups of full tiles)
|
||||||
switch (rx)
|
switch (rx)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -137,28 +157,35 @@ void expand(char * dp, const char * grid, char px, char py)
|
||||||
expandrow3(cdp, cgrid, ry);
|
expandrow3(cdp, cgrid, ry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Next row
|
||||||
cdp += 40;
|
cdp += 40;
|
||||||
ry += 4;
|
ry += 4;
|
||||||
|
|
||||||
|
// Next tile
|
||||||
if (ry == 16)
|
if (ry == 16)
|
||||||
{
|
{
|
||||||
ry = 0;
|
ry = 0;
|
||||||
cgrid += 16;
|
cgrid += 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char grid[16][16];
|
char grid[32][32];
|
||||||
|
|
||||||
#pragma align(grid, 256)
|
#pragma align(grid, 256)
|
||||||
|
|
||||||
|
// Raster IRQs for split screen
|
||||||
|
|
||||||
RIRQCode blank, scroll, bottom;
|
RIRQCode blank, scroll, bottom;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
for(char y=0; y<16; y++)
|
// Init grid with random data
|
||||||
|
for(char y=0; y<32; y++)
|
||||||
{
|
{
|
||||||
for(char x=0; x<16; x++)
|
for(char x=0; x<32; x++)
|
||||||
{
|
{
|
||||||
grid[y][x] = rand() & 3;
|
grid[y][x] = rand() & 3;
|
||||||
}
|
}
|
||||||
|
@ -166,18 +193,22 @@ int main(void)
|
||||||
|
|
||||||
vic.color_border = 0;
|
vic.color_border = 0;
|
||||||
|
|
||||||
|
// Setup split screen
|
||||||
rirq_init(true);
|
rirq_init(true);
|
||||||
|
|
||||||
|
// Blank display after top section
|
||||||
rirq_build(&blank, 1);
|
rirq_build(&blank, 1);
|
||||||
rirq_write(&blank, 0, &vic.ctrl1, 0);
|
rirq_write(&blank, 0, &vic.ctrl1, 0);
|
||||||
rirq_set(0, 46 + 5 * 8, &blank);
|
rirq_set(0, 46 + 5 * 8, &blank);
|
||||||
|
|
||||||
|
// Setup scrolling area
|
||||||
rirq_build(&scroll, 3);
|
rirq_build(&scroll, 3);
|
||||||
rirq_delay(&scroll, 10);
|
rirq_delay(&scroll, 10);
|
||||||
rirq_write(&scroll, 1, &vic.ctrl1, VIC_CTRL1_DEN);
|
rirq_write(&scroll, 1, &vic.ctrl1, VIC_CTRL1_DEN);
|
||||||
rirq_write(&scroll, 2, &vic.ctrl2, 0);
|
rirq_write(&scroll, 2, &vic.ctrl2, 0);
|
||||||
rirq_set(1, 54 + 5 * 8, &scroll);
|
rirq_set(1, 54 + 5 * 8, &scroll);
|
||||||
|
|
||||||
|
// Wait for bottom of screen
|
||||||
rirq_build(&bottom, 2);
|
rirq_build(&bottom, 2);
|
||||||
rirq_write(&bottom, 0, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL);
|
rirq_write(&bottom, 0, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL);
|
||||||
rirq_write(&bottom, 1, &vic.ctrl2, VIC_CTRL2_CSEL);
|
rirq_write(&bottom, 1, &vic.ctrl2, VIC_CTRL2_CSEL);
|
||||||
|
@ -187,46 +218,59 @@ int main(void)
|
||||||
|
|
||||||
rirq_start();
|
rirq_start();
|
||||||
|
|
||||||
|
// Movement data
|
||||||
int py = 40 * 32, px = 40 * 32, dy = 0, dx = 0, ax = 0, ay = 0;
|
int py = 40 * 32, px = 40 * 32, dy = 0, dx = 0, ax = 0, ay = 0;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Grid position using 13.5 fractions
|
||||||
int rx = px >> 5, ry = py >> 5;
|
int rx = px >> 5, ry = py >> 5;
|
||||||
|
|
||||||
|
// Wait for next raster
|
||||||
vic.color_border++;
|
vic.color_border++;
|
||||||
rirq_wait();
|
rirq_wait();
|
||||||
vic.color_border--;
|
vic.color_border--;
|
||||||
|
|
||||||
|
// Update vertical scroll position
|
||||||
rirq_data(&blank, 0, ((7 - ry) & 7) | VIC_CTRL1_DEN | VIC_CTRL1_BMM | VIC_CTRL1_ECM);
|
rirq_data(&blank, 0, ((7 - ry) & 7) | VIC_CTRL1_DEN | VIC_CTRL1_BMM | VIC_CTRL1_ECM);
|
||||||
|
|
||||||
|
// Dynamic wait based on vertical scroll position to counter bad lines
|
||||||
if ((ry & 7) == 0)
|
if ((ry & 7) == 0)
|
||||||
rirq_data(&scroll, 0, 4);
|
rirq_data(&scroll, 0, 4);
|
||||||
else
|
else
|
||||||
rirq_data(&scroll, 0, 10);
|
rirq_data(&scroll, 0, 10);
|
||||||
|
|
||||||
|
// Update vertical and horizontal scroll position
|
||||||
rirq_data(&scroll, 1, ((7 - ry) & 7) | VIC_CTRL1_DEN);
|
rirq_data(&scroll, 1, ((7 - ry) & 7) | VIC_CTRL1_DEN);
|
||||||
rirq_data(&scroll, 2, (7 - rx) & 7);
|
rirq_data(&scroll, 2, (7 - rx) & 7);
|
||||||
|
|
||||||
|
// Expand grid at current location
|
||||||
expand(screen + 200, &(grid[0][0]), rx >> 3, ry >> 3);
|
expand(screen + 200, &(grid[0][0]), rx >> 3, ry >> 3);
|
||||||
|
|
||||||
|
// Update screen velocity using differential equation
|
||||||
dx += ax;
|
dx += ax;
|
||||||
dy += ay;
|
dy += ay;
|
||||||
|
|
||||||
|
// New force
|
||||||
if ((rand() & 127) == 0)
|
if ((rand() & 127) == 0)
|
||||||
{
|
{
|
||||||
ax = (rand() & 63) - 32;
|
ax = (rand() & 63) - 32;
|
||||||
ay = (rand() & 63) - 32;
|
ay = (rand() & 63) - 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some friction
|
||||||
dx -= (dx + 8) >> 4;
|
dx -= (dx + 8) >> 4;
|
||||||
dy -= (dy + 8) >> 4;
|
dy -= (dy + 8) >> 4;
|
||||||
|
|
||||||
|
// Update position reflect at borders
|
||||||
py += dy;
|
py += dy;
|
||||||
if (py < 0 || py > 10 * 8 * 4 * 32)
|
if (py < 0 || py > 26 * 8 * 4 * 32)
|
||||||
{
|
{
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
py += dy;
|
py += dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
px += dx;
|
px += dx;
|
||||||
if (px < 0 || px > 6 * 8 * 4 * 32)
|
if (px < 0 || px > 22 * 8 * 4 * 32)
|
||||||
{
|
{
|
||||||
dx = -dx;
|
dx = -dx;
|
||||||
px += dx;
|
px += dx;
|
||||||
|
|
|
@ -3,14 +3,20 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Screen and color space
|
||||||
#define screen ((byte *)0x0400)
|
#define screen ((byte *)0x0400)
|
||||||
#define color ((byte *)0xd800)
|
#define color ((byte *)0xd800)
|
||||||
|
|
||||||
|
// Macro for easy access to screen space
|
||||||
#define sline(x, y) (screen + 40 * (y) + (x))
|
#define sline(x, y) (screen + 40 * (y) + (x))
|
||||||
|
|
||||||
|
// Column buffer for one prepared column of tunnel
|
||||||
char rbuff[25];
|
char rbuff[25];
|
||||||
|
|
||||||
|
// Copy the prepared tunnel column to screen
|
||||||
void expand(char x)
|
void expand(char x)
|
||||||
{
|
{
|
||||||
|
// Unroll for each row
|
||||||
#assign y 0
|
#assign y 0
|
||||||
#repeat
|
#repeat
|
||||||
sline(0, y)[x] = rbuff[y];
|
sline(0, y)[x] = rbuff[y];
|
||||||
|
@ -18,8 +24,13 @@ void expand(char x)
|
||||||
#until y == 25
|
#until y == 25
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scrolling left, copying new column. This is split into two
|
||||||
|
// unrolled sections so the update of the new column can race the
|
||||||
|
// beam
|
||||||
|
|
||||||
void scrollLeft(void)
|
void scrollLeft(void)
|
||||||
{
|
{
|
||||||
|
// First 12 rows scroll left and copy new column
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
{
|
{
|
||||||
#assign y 0
|
#assign y 0
|
||||||
|
@ -34,6 +45,7 @@ void scrollLeft(void)
|
||||||
#assign y y + 1
|
#assign y y + 1
|
||||||
#until y == 12
|
#until y == 12
|
||||||
|
|
||||||
|
// Final 13 rows scroll left and copy new column
|
||||||
for(char x=0; x<39; x++)
|
for(char x=0; x<39; x++)
|
||||||
{
|
{
|
||||||
#assign y 12
|
#assign y 12
|
||||||
|
@ -49,6 +61,10 @@ void scrollLeft(void)
|
||||||
#until y == 25
|
#until y == 25
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scrolling right, copying new column. This is split into two
|
||||||
|
// unrolled sections so the update of the new column can race the
|
||||||
|
// beam
|
||||||
|
|
||||||
void scrollRight(void)
|
void scrollRight(void)
|
||||||
{
|
{
|
||||||
for(char x=39; x>0; x--)
|
for(char x=39; x>0; x--)
|
||||||
|
@ -80,19 +96,26 @@ void scrollRight(void)
|
||||||
#until y == 25
|
#until y == 25
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Top and bottom row of the tunnel
|
||||||
|
|
||||||
char ytop[256], ybottom[256];
|
char ytop[256], ybottom[256];
|
||||||
|
|
||||||
|
// Prepare one column of the tunnel
|
||||||
|
|
||||||
void prepcol(char xi)
|
void prepcol(char xi)
|
||||||
{
|
{
|
||||||
char yt, yb;
|
char yt, yb;
|
||||||
signed char dyt, dyb;
|
signed char dyt, dyb;
|
||||||
|
|
||||||
|
// Current height of top and bottom
|
||||||
yt = ytop[(char)(xi + 0)];
|
yt = ytop[(char)(xi + 0)];
|
||||||
yb = ybottom[(char)(xi + 0)];
|
yb = ybottom[(char)(xi + 0)];
|
||||||
|
|
||||||
|
// Height of column to the left for diagonal
|
||||||
dyt = yt - ytop[(char)(xi - 1)];
|
dyt = yt - ytop[(char)(xi - 1)];
|
||||||
dyb = yb - ybottom[(char)(xi - 1)];
|
dyb = yb - ybottom[(char)(xi - 1)];
|
||||||
|
|
||||||
|
// Fill top, center and bottom range
|
||||||
for(char i=0; i<yt; i++)
|
for(char i=0; i<yt; i++)
|
||||||
rbuff[i] = 160;
|
rbuff[i] = 160;
|
||||||
for(char i=yt; i<yb; i++)
|
for(char i=yt; i<yb; i++)
|
||||||
|
@ -100,6 +123,7 @@ void prepcol(char xi)
|
||||||
for(char i=yb; i<25; i++)
|
for(char i=yb; i<25; i++)
|
||||||
rbuff[i] = 160;
|
rbuff[i] = 160;
|
||||||
|
|
||||||
|
// Select transitional characters based on slope
|
||||||
if (dyt < 0)
|
if (dyt < 0)
|
||||||
rbuff[yt] = 105;
|
rbuff[yt] = 105;
|
||||||
else if (dyt > 0)
|
else if (dyt > 0)
|
||||||
|
@ -112,6 +136,7 @@ void prepcol(char xi)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize tunnel with "random" data
|
||||||
void buildTunnel(void)
|
void buildTunnel(void)
|
||||||
{
|
{
|
||||||
signed char yt = 1, yb = 24, dyt = 1, dyb = -1;
|
signed char yt = 1, yb = 24, dyt = 1, dyb = -1;
|
||||||
|
@ -152,49 +177,64 @@ void buildTunnel(void)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Clear the screen
|
||||||
|
|
||||||
memset(screen, 0x20, 1000);
|
memset(screen, 0x20, 1000);
|
||||||
memset(color, 7, 1000);
|
memset(color, 7, 1000);
|
||||||
|
|
||||||
vic.color_back = VCOL_BLACK;
|
vic.color_back = VCOL_BLACK;
|
||||||
vic.color_border = VCOL_BLACK;
|
vic.color_border = VCOL_BLACK;
|
||||||
|
|
||||||
|
// Build tunnel
|
||||||
|
|
||||||
buildTunnel();
|
buildTunnel();
|
||||||
|
|
||||||
|
// Initial fill of screen
|
||||||
|
|
||||||
for(char i=0; i<40; i++)
|
for(char i=0; i<40; i++)
|
||||||
{
|
{
|
||||||
prepcol(i);
|
prepcol(i);
|
||||||
expand(i);
|
expand(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now start moving
|
||||||
int xpos = 0, dx = 0, ax = 1;
|
int xpos = 0, dx = 0, ax = 1;
|
||||||
int xi = 0, pxi = 0;
|
int xi = 0, pxi = 0;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Random change of direction
|
||||||
unsigned r = rand();
|
unsigned r = rand();
|
||||||
if ((r & 127) == 0)
|
if ((r & 127) == 0)
|
||||||
ax = -ax;
|
ax = -ax;
|
||||||
|
|
||||||
|
// Acceleration
|
||||||
dx += ax;
|
dx += ax;
|
||||||
if (dx > 32)
|
if (dx > 32)
|
||||||
dx = 32;
|
dx = 32;
|
||||||
else if (dx < -32)
|
else if (dx < -32)
|
||||||
dx = -32;
|
dx = -32;
|
||||||
|
|
||||||
|
// Movement
|
||||||
xpos += dx;
|
xpos += dx;
|
||||||
pxi = xi;
|
pxi = xi;
|
||||||
xi = xpos >> 5;
|
xi = xpos >> 5;
|
||||||
|
|
||||||
|
// Check if we cross a character boundary, and if so prepare
|
||||||
|
// the new column
|
||||||
if (pxi < xi)
|
if (pxi < xi)
|
||||||
prepcol(xi + 39);
|
prepcol(xi + 39);
|
||||||
else if (pxi > xi)
|
else if (pxi > xi)
|
||||||
prepcol(xi + 0);
|
prepcol(xi + 0);
|
||||||
|
|
||||||
|
// Wait one frame
|
||||||
vic_waitTop();
|
vic_waitTop();
|
||||||
vic_waitBottom();
|
vic_waitBottom();
|
||||||
|
|
||||||
|
// Update pixel level scrolling
|
||||||
vic.ctrl2 = (7 - (xpos >> 2)) & 7;
|
vic.ctrl2 = (7 - (xpos >> 2)) & 7;
|
||||||
|
|
||||||
|
// Character level scrolling if needed
|
||||||
if (pxi < xi)
|
if (pxi < xi)
|
||||||
scrollLeft();
|
scrollLeft();
|
||||||
else if (pxi > xi)
|
else if (pxi > xi)
|
||||||
|
|
|
@ -12,29 +12,38 @@ int spx, spy;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
// Copy the sprite data
|
||||||
memcpy(SpriteData, spdata, 128);
|
memcpy(SpriteData, spdata, 128);
|
||||||
|
|
||||||
|
// Initalize the sprite system
|
||||||
spr_init((char*)0x0400);
|
spr_init((char*)0x0400);
|
||||||
|
|
||||||
|
// Center screen position
|
||||||
spx = 160;
|
spx = 160;
|
||||||
spy = 100;
|
spy = 100;
|
||||||
|
|
||||||
|
// Two sprites, one black in front hires and one multicolor in back
|
||||||
spr_set(0, true, spx, spy, 0x03c0 / 64, VCOL_BLACK, false, false, false);
|
spr_set(0, true, spx, spy, 0x03c0 / 64, VCOL_BLACK, false, false, false);
|
||||||
spr_set(1, true, spx, spy, 0x0380 / 64, VCOL_ORANGE, true, false, false);
|
spr_set(1, true, spx, spy, 0x0380 / 64, VCOL_ORANGE, true, false, false);
|
||||||
|
|
||||||
|
// Multicolor sprite colors
|
||||||
vic.spr_mcolor0 = VCOL_BROWN;
|
vic.spr_mcolor0 = VCOL_BROWN;
|
||||||
vic.spr_mcolor1 = VCOL_WHITE;
|
vic.spr_mcolor1 = VCOL_WHITE;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
// Poll joytick
|
||||||
joy_poll(1);
|
joy_poll(1);
|
||||||
|
|
||||||
|
// Change position according to joystick
|
||||||
spx += joyx[1];
|
spx += joyx[1];
|
||||||
spy += joyy[1];
|
spy += joyy[1];
|
||||||
|
|
||||||
|
// Move sprites on screen
|
||||||
spr_move(0, spx, spy);
|
spr_move(0, spx, spy);
|
||||||
spr_move(1, spx, spy);
|
spr_move(1, spx, spy);
|
||||||
|
|
||||||
|
// Wait for one frame iteration
|
||||||
vic_waitFrame();
|
vic_waitFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue