initial commit

This commit is contained in:
2026-07-18 20:34:55 +02:00
commit 59ad004c96
474 changed files with 226635 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
#!/bin/sh
( cd fractals ; ./build.sh )
( cd games ; ./build.sh )
( cd hires ; ./build.sh )
( cd hiresmc ; ./build.sh )
( cd particles ; ./build.sh )
( cd kernalio ; ./build.sh )
( cd memmap ; ./build.sh )
( cd rasterirq ; ./build.sh )
( cd scrolling ; ./build.sh )
( cd sprites ; ./build.sh )
( cd stdio ; ./build.sh )
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
../../bin/oscar64 mbtext.c -n
../../bin/oscar64 mbhires.c -n
../../bin/oscar64 mbmulti.c -n
../../bin/oscar64 mbmulti3d.c -n
../../bin/oscar64 mbfixed.c -n -O3
../../bin/oscar64 mbzoom.c -n -O3
+6
View File
@@ -0,0 +1,6 @@
call ..\..\bin\oscar64 mbtext.c -n
call ..\..\bin\oscar64 mbhires.c -n
call ..\..\bin\oscar64 mbmulti.c -n
call ..\..\bin\oscar64 mbmulti3d.c -n
call ..\..\bin\oscar64 mbfixed.c -n -O3
call ..\..\bin\oscar64 mbzoom.c -n -O3
+14
View File
@@ -0,0 +1,14 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: mbtext.prg mbtext.prg mbhires.prg mbmulti.prg mbmulti3d.prg mbfixed.prg mbzoom.prg
mbfixed.prg: mbfixed.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) -O3 $<
mbzoom.prg: mbzoom.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) -O3 $<
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg
+100
View File
@@ -0,0 +1,100 @@
#include <string.h>
#include <c64/vic.h>
#include <c64/memmap.h>
#include <conio.h>
#include <fixmath.h>
// Address of hires buffer and color buffers
#define Screen ((char *)0xe000)
#define Color ((char *)0xc800)
#define Color2 ((char *)0xd800)
// Bit patterns for eight different color pairs
char colors[] = {
0xff, 0xff,
0xee, 0xbb,
0xaa, 0xaa,
0x88, 0x22,
0x44, 0x11,
0x55, 0x55,
0xdd, 0x77,
0x33, 0xcc
};
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Turn of the kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch VIC into multicolor bitmap mode
vic_setmode(VICM_HIRES_MC, Color, Screen);
// Clear the screen and set the colors
vic.color_back = 0x00;
memset(Screen, 0, 8000);
memset(Color, 0x27, 1000);
memset(Color2, 0x03, 1000);
// Loop over all pixels
int py, px;
for(py=0; py<100; py++)
{
for(px=0; px<160; px++)
{
// Value in the complex plane
// int xz = (int)(((float)px * (3.5 / 160.0) - 2.5) * 4096 + 0.5);
// int yz = (int)(((float)py * (2.4 / 100.0) - 1.2) * 4096 + 0.5);
int xz = lmul8f8s(px, (int)((3.5 / 160.0) * 4096 * 256)) - (int)(2.5 * 4096);
int yz = lmul8f8s(py, (int)((2.4 / 100.0) * 4096 * 256)) - (int)(1.2 * 4096);
// Iterate up to 32 times
int x = 0, y = 0;
int i;
for(i=0; i<32; i++)
{
unsigned long xq = lsqr4f12s(x), yq = lsqr4f12s(y);
if (xq + yq >= 0x04000000UL) break;
int xt = (int)(xq >> 12) - (int)(yq >> 12) + xz;
y = 2 * lmul4f12s(x, y) + yz;
x = xt;
}
if (i < 32)
{
// Position on screen
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (px & ~3);
// Mask of pixels to change
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];
// Put the pixels into the image
dp[0] |= c0 & mask;
dp[1] |= c1 & mask;
}
}
}
// Re-enable the kernal
mmap_set(MMAP_NO_BASIC);
// Wait for key press
getch();
// Restore VIC state
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
+65
View File
@@ -0,0 +1,65 @@
#include <string.h>
#include <c64/vic.h>
#include <c64/memmap.h>
#include <conio.h>
// Address of hires buffer and color buffer
#define Screen ((char *)0xe000)
#define Color ((char *)0xc800)
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Turn of the kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch VIC into hires mode
vic_setmode(VICM_HIRES, Color, Screen);
// Clear the screen
memset(Screen, 0, 8000);
memset(Color, 0x10, 1000);
// Loop over all pixels
int py, px;
for(py=0; py<200; py++)
{
for(px=0; px<320; px++)
{
// Value in the complex plane
float xz = (float)px * (3.5 / 320.0)- 2.5;
float yz = (float)py * (2.0 / 200.0) - 1.0;
// Iterate up to 32 times
float x = 0.0, y = 0.0;
int i;
for(i=0; i<32; i++)
{
if (x * x + y * y > 4.0) break;
float xt = x * x - y * y + xz;
y = 2 * x * y + yz;
x = xt;
}
// Set a pixel if exceeds bound in less than 32 iterations
if (i < 32)
Screen[320 * (py >> 3) + (py & 7) + (px & ~7)] |= 0x80 >> (px & 7);
}
}
// Re-enable the kernal
mmap_set(MMAP_NO_BASIC);
// Wait for key press
getch();
// Restore VIC state
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
+94
View File
@@ -0,0 +1,94 @@
#include <string.h>
#include <c64/vic.h>
#include <c64/memmap.h>
#include <conio.h>
// Address of hires buffer and color buffers
#define Screen ((char *)0xe000)
#define Color ((char *)0xc800)
#define Color2 ((char *)0xd800)
// Bit patterns for eight different color pairs
char colors[] = {
0xff, 0xff,
0xee, 0xbb,
0xaa, 0xaa,
0x88, 0x22,
0x44, 0x11,
0x55, 0x55,
0xdd, 0x77,
0x33, 0xcc
};
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Turn of the kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch VIC into multicolor bitmap mode
vic_setmode(VICM_HIRES_MC, Color, Screen);
// Clear the screen and set the colors
vic.color_back = 0x00;
memset(Screen, 0, 8000);
memset(Color, 0x27, 1000);
memset(Color2, 0x03, 1000);
// Loop over all pixels
int py, px;
for(py=0; py<100; py++)
{
for(px=0; px<160; px++)
{
// Value in the complex plane
float xz = (float)px * (3.5 / 160.0)- 2.5;
float yz = (float)py * (2.4 / 100.0) - 1.2;
// Iterate up to 32 times
float x = 0.0, y = 0.0;
int i;
for(i=0; i<32; i++)
{
if (x * x + y * y > 4.0) break;
float xt = x * x - y * y + xz;
y = 2 * x * y + yz;
x = xt;
}
if (i < 32)
{
// Position on screen
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (px & ~3);
// Mask of pixels to change
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];
// Put the pixels into the image
dp[0] |= c0 & mask;
dp[1] |= c1 & mask;
}
}
}
// Re-enable the kernal
mmap_set(MMAP_NO_BASIC);
// Wait for key press
getch();
// Restore VIC state
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
+183
View File
@@ -0,0 +1,183 @@
#include <string.h>
#include <c64/vic.h>
#include <c64/memmap.h>
#include <conio.h>
#include <math.h>
// Address of hires buffer and color buffers
#define Screen ((char *)0xe000)
#define Color1 ((char *)0xc800)
#define Color2 ((char *)0xd800)
// Bit patterns for two different color pairs and eight shades
byte colors[2][17] =
{
{0x00,
0x44, 0x44, 0x55, 0x55, 0xdd, 0xdd, 0xff, 0xff,
0x88, 0x88, 0xaa, 0xaa, 0xee, 0xee, 0xff, 0xff,
},
{0x00,
0x00, 0x11, 0x11, 0x55, 0x55, 0x77, 0x77, 0xff,
0x00, 0x22, 0x22, 0xaa, 0xaa, 0xbb, 0xbb, 0xff,
}
};
// Fill a vertical line x from py to ty with color c
void VLine(int x, int py, int ty, char c)
{
// Clip boundaries
if (py < 0)
py = 0;
if (ty > 100)
ty = 100;
// Check if there are pixel to draw
if (py < ty)
{
// Calculate top address and mask
char mask = 0xc0 >> (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;
// Invert mask to cover the unchanged portion
mask = ~mask;
// Loop over all pixels
char h = ty - py;
while (h)
{
// Apply color to memory
dp[0] = (dp[0] & mask) | c0;
dp[1] = (dp[1] & mask) | c1;
// Two pixel lines down
dp += 2;
if (!((int)dp & 7))
dp += 312;
h--;
}
}
}
// Iterate up to 32 iterations and return a smoothed height
float iter(float xz, float yz)
{
float x = 0.0, y = 0.0, r;
int i;
for(i=0; i<32; i++)
{
r = x * x + y * y;
if (r > 64.0) break;
float xt = x * x - y * y + xz;
y = 2 * x * y + yz;
x = xt;
}
if (i == 32)
return 32;
else
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)
{
float dx = h - hl, dz = h - hu, dy = 0.1;
float dd = sqrt(dx * dx + dy * dy + dz * dz);
int ni = (int)floor((-2 * dx + dy + dz) / dd * 0.408 * 8);
if (ni < 0) ni = 0; else if (ni > 7) ni = 7;
return ni;
}
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Turn of the kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch VIC into multicolor bitmap mode
vic_setmode(VICM_HIRES_MC, Color1, Screen);
// Clear the screen and set the colors
vic.color_back = 0x00;
vic.color_border = 0x00;
memset(Screen, 0, 8000);
memset(Color1, 0x26, 1000);
memset(Color2, 0x0f, 1000);
// Height of previous row, needed for lighting
float hl[200];
// Rotation of complex plane
float w = -0.7;
float co = cos(w), si = sin(w);
// Loop from left to right
for(int x=-1; x<160; x+= 1)
{
// Loop from far to nead
int py = 20;
float hu = 0;
for(int y=1; y<200; y+= 1)
{
// Inverse 3D projection
float fz = 2.0 / (float)y;
float fx = (float)(x - 80) * fz / 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 dp = iter(rx, rz);
float v = 2 * dp;
if (v < 1.0) v = 1.0;
float fy = 5.0 * pow(2.0, - v * 0.4);
// Calculate light
int ni = light(hl[y], hu, fy);
// Update left column
hl[y] = fy;
hu = fy;
// Forward 3D projection
int ty = 20 + y / 2 + (int)(floor(fy / fz));
// color of pixel
int c;
if (dp != 32)
c = 1 + ni + 8 * ((int)floor(dp) & 1);
else
c = 0;
// Draw line if not dummy left row
if (x >= 0)
VLine(x, py, ty, c);
py = ty;
}
}
// Re-enable the kernal
mmap_set(MMAP_NO_BASIC);
// Wait for key press
getch();
// Restore VIC state
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

+36
View File
@@ -0,0 +1,36 @@
#include <string.h>
#define Screen ((char *)0x0400)
#define Color ((char *)0xd800)
int main(void)
{
memset(Screen, 160, 1024);
int py, px;
for(py=0; py<25; py++)
{
for(px=0; px<40; px++)
{
float xz = (float)px * (3.5 / 40.0)- 2.5;
float yz = (float)py * (2.0 / 25.0) - 1.0;
float x = 0.0, y = 0.0;
int i;
for(i=0; i<=14; i++)
{
if (x * x + y * y > 4.0) break;
float xt = x * x - y * y + xz;
y = 2 * x * y + yz;
x = xt;
}
i--;
Color[py * 40 + px] = i;
}
}
return 0;
}
+312
View File
@@ -0,0 +1,312 @@
#include <string.h>
#include <conio.h>
#include <c64/vic.h>
#define Screen ((char *)0x0400)
#define Color ((char *)0xd800)
// Lookup table for squares from 0..255
__striped unsigned sqb[256];
// Shift byte right and left by 4
char shlb4[256], shrb4[256];
#pragma align(sqb, 256);
// Square an unsigned int into an unsigned long
inline unsigned long ssquare(unsigned x)
{
// Split into low byte and highbyte, so we have x = a + 0x100 * b
unsigned a = x & 0xff;
unsigned b = x >> 8;
// So now we calculate (a + 0x100 * b)²
// Result will be a² + 0x100 * 2 * a * b + 0x10000 * b²
// with 2 * a * b == (a + b)² - a² - b²
// We can cover all cases with the square table except if a + b >= 0x100
// in this case we have abp := a + b - 0x100
// (abp + 0x100)² == abp² + 2 * 0x100 * abp + 0x10000
// Get squares of the bytes and the sum of the bytes
unsigned a2 = sqb[a], b2 = sqb[b];
unsigned apb = a + b;
// First approximation approximation
// a² + 0x10000 * b²
unsigned long sum = a2 + ((unsigned long)b2 << 16);
// Check if a + b >= 0x100
if (apb & 0xff00)
{
apb &= 0xff;
sum += 0x1000000UL;
sum += (unsigned long)apb << 17;
sum += (unsigned long)sqb[apb] << 8;
}
else
{
apb &= 0xff;
sum += (unsigned long)sqb[apb] << 8;
}
// Now w have a² + 0x1000 * b² + (a + b)²
sum -= (unsigned long)a2 << 8;
sum -= (unsigned long)b2 << 8;
// And finally the complete result
return sum;
}
// Signed square of x
inline long sq(int x)
{
if (x < 0)
x = -x;
return ssquare(x);
}
// Colors to fill in the different levels
static const char colors[32] = {
VCOL_BLUE,
VCOL_LT_BLUE,
VCOL_WHITE,
VCOL_LT_GREEN,
VCOL_GREEN,
VCOL_YELLOW,
VCOL_ORANGE,
VCOL_RED,
VCOL_PURPLE,
VCOL_BLUE,
VCOL_BLUE,
VCOL_LT_BLUE,
VCOL_LT_BLUE,
VCOL_WHITE,
VCOL_WHITE,
VCOL_LT_GREEN,
VCOL_LT_GREEN,
VCOL_GREEN,
VCOL_GREEN,
VCOL_YELLOW,
VCOL_YELLOW,
VCOL_ORANGE,
VCOL_ORANGE,
VCOL_RED,
VCOL_RED,
VCOL_PURPLE,
VCOL_PURPLE,
VCOL_LT_GREY,
VCOL_LT_GREY,
VCOL_MED_GREY,
VCOL_MED_GREY,
VCOL_DARK_GREY,
};
inline int shr12(long l)
{
char b3 = (l >> 24) & 0xff;
char b2 = (l >> 16) & 0xff;
char b1 = (l >> 8) & 0xff;
char a0 = shrb4[b1] | shlb4[b2];
char a1 = shrb4[b2] | shlb4[b3];
return a0 | (a1 << 8);
}
// Return color for a given coordinate in the complex plane using
// 12.4bit fixed numbers using m'=m²+b
inline char fcolor(int xz, int yz)
{
// Start value for iteration is the offset value itself
int x = xz, y = yz;
// Iterate up to 32 steps
for(int i=0; i<32; i++)
{
// Build squares of real and imaginary component
long xx = sq(x), yy = sq(y), xxyy = sq(x + y);
long xxpyy = xx + yy;
// Use squares to check for exit condition of sure
// to progress towards infinity
if (xxpyy >= 4L * 4096 * 4096) return colors[i];
// Next iteration values using complex arithmetic
// Mx' = Mx² - My² + Bx
// My' = 2 * Mx * My + By = (Mx + My)² - Mx² - My² + By
x = shr12(xx - yy + 2048) + xz;
y = shr12(xxyy - xxpyy + 2048) + yz;
}
// More than maximum number of iterations, so assume progress
// towards zero
return VCOL_BLACK;
}
// Fill a row with color
void fill_row(char py, int cix, int yz, int cis)
{
int xz = cix;
for(int px=0; px<40; px++)
{
Color[py * 40 + px] = fcolor(xz, yz);
xz += cis;
}
}
// Fill a column with color
void fill_column(char px, int xz, int ciy, int cis)
{
int yz = ciy;
for(int py=0; py<25; py++)
{
Color[py * 40 + px] = fcolor(xz, yz);
yz += cis;
}
}
// Fill the complete image
void fill_image(int cix, int ciy, int cis)
{
int yz = ciy;
for(int py=0; py<25; py++)
{
fill_row(py, cix, yz, cis);
yz += cis;
}
}
// Scroll screen to the left
void scroll_left(void)
{
for(char x=0; x<39; x++)
{
#pragma unroll(full)
for(char y=0; y<25; y++)
{
Color[y * 40 + x] = Color[y * 40 + x + 1];
}
}
}
// Scroll screen to the right
void scroll_right(void)
{
for(signed char x=38; x>=0; x--)
{
#pragma unroll(full)
for(char y=0; y<25; y++)
{
Color[y * 40 + x + 1] = Color[y * 40 + x];
}
}
}
// Scroll screen up
void scroll_up(void)
{
for(char x=0; x<40; x++)
{
#pragma unroll(full)
for(char y=0; y<24; y++)
{
Color[y * 40 + x] = Color[(y + 1) * 40 + x];
}
}
}
// Scroll screen down
void scroll_down(void)
{
for(char x=0; x<40; x++)
{
#pragma unroll(full)
for(char y=0; y<24; y++)
{
Color[(24 - y) * 40 + x] = Color[(23 - y) * 40 + x];
}
}
}
int main(void)
{
// Initialize square table
for(unsigned i=0; i<256; i++)
{
sqb[i] = i * i;
shlb4[i] = i << 4;
shrb4[i] = i >> 4;
}
// Clear screen
memset(Screen, 160, 1024);
// Start coordinates in float
float cx = -0.4;
float cy = 0.0;
float cw = 3.2;
// Convert to top, left and step in 12.4 fixed point
int cix = (int)((cx - 0.5 * cw) * 4096);
int ciy = (int)((cy - 12.0 * cw / 40.0) * 4096);
int cis = (int)(cw / 40.0 * 4096);
// Initial image
fill_image(cix, ciy, cis);
for(;;)
{
// Wait for keypress
char ch = getch();
switch (ch)
{
case 'S':
ciy += cis;
scroll_up();
fill_row(24, cix, ciy + 24 * cis, cis);
break;
case 'W':
ciy -= cis;
scroll_down();
fill_row(0, cix, ciy, cis);
break;
case 'A':
cix -= cis;
scroll_right();
fill_column(0, cix, ciy, cis);
break;
case 'D':
cix += cis;
scroll_left();
fill_column(39, cix + 39 * cis, ciy, cis);
break;
case '+':
cix += 20 * cis;
ciy += 12 * cis;
cis = cis * 2 / 3;
cix -= 20 * cis;
ciy -= 12 * cis;
fill_image(cix, ciy, cis);
break;
case '-':
cix += 20 * cis;
ciy += 12 * cis;
cis = cis * 3 / 2;
cix -= 20 * cis;
ciy -= 12 * cis;
fill_image(cix, ciy, cis);
break;
}
}
return 0;
}
+664
View File
@@ -0,0 +1,664 @@
#include <c64/joystick.h>
#include <c64/vic.h>
#include <c64/sprites.h>
#include <c64/memmap.h>
#include <c64/rasterirq.h>
#include <c64/sid.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
// Character set
char charset[2048] = {
#embed "../resources/breakoutchars.bin"
};
char spriteset[2048] = {
#embed "../resources/breakoutsprites.bin"
};
byte * const Screen = (byte *)0xc800;
byte * const Font = (byte *)0xd000;
byte * const Color = (byte *)0xd800;
byte * const Sprites = (byte *)0xd800;
unsigned flashingBricks[32];
char numFlashingBricks[4];
// 0123456789012345678901234567890123456789
const char StatusText[] = s" Score: 000000 High: 000000 Lives: 0 ";
void status_init(void)
{
for(char i=0; i<40; i++)
{
if (StatusText[i] != ' ')
{
Screen[i] = StatusText[i];
Color[i] = 7;
}
}
}
// Increment the score from a given digit on
void score_inc(char digit, unsigned val)
{
// Lowest digit to increment
char at = 13 - digit;
// Loop while there is still score to account for
while (val)
{
// Increment one character
char ch = Screen[at] + val % 10;
// Remove low digit from number
val /= 10;
// Check overflow
if (ch > '9')
{
ch -= 10;
val++;
}
Screen[at] = ch;
// Next higher character
at --;
}
}
// Reset score and update high score
void score_reset(void)
{
// Find first digit, where score and highscore differ
char i = 0;
while (i < 6 && Screen[i + 8] == Screen[i + 22])
i++;
// Check if new score is higher
if (i < 6 && Screen[i + 8] > Screen[i + 22])
{
// If so, copy to highscore
while (i < 6)
{
Screen[i + 22] = Screen[i + 8];
i++;
}
}
// Clear score
for(char i=0; i<6; i++)
Screen[i + 8] = '0';
}
void brick_put(char x, char y, char b, char c)
{
char * cp = Color + 40 * y + x;
cp[ 0] = c;
cp[ 1] = c;
cp[ 2] = c;
cp[40] = c;
cp[41] = c;
cp[42] = c;
cp[81] = 15;
cp[82] = 15;
cp[83] = 15;
char * sp = Screen + 40 * y + x;
sp[ 0] = b | 0;
sp[ 1] = b | 1;
sp[ 2] = b | 2;
sp[40] = b | 3;
sp[41] = b | 4;
sp[42] = b | 5;
sp[43] = 103 - (x & 1) - 2 * (y & 1);
sp[81] = 101 - (x & 1) + 2 * (y & 1);
sp[82] = 100 + (x & 1) + 2 * (y & 1);
sp[83] = 101 - (x & 1) + 2 * (y & 1);
}
void brick_init(void)
{
for(char y=0; y<25; y++)
{
for(char x=0; x<40; x++)
{
Screen[40 * y + x] = 96 + (x & 1) + 2 * (y & 1);// + 4 * (x == 0 || y == 0);
}
}
status_init();
for(char y=0; y<8; y++)
{
for(char x=0; x<12; x++)
{
brick_put(3 * x + 2, 2 * y + 1, 128 + (x / 4) * 8, 8 + y);
}
}
}
void brick_hit(char x, char y)
{
__assume(x < 40 && y < 25);
char c = Screen[40 * y + x + 0];
if (c >= 128)
{
c &= 7;
if (c >= 3)
{
y --;
c -= 3;
}
x -= c;
unsigned bi = 256 * y + x;
char i = 0, n = numFlashingBricks[3];
while (i < n && flashingBricks[i] != bi)
i++;
if (i == n)
{
flashingBricks[i] = bi;
numFlashingBricks[3]++;
char * cp = Color + 40 * y + x;
cp[ 0] = 9;
cp[ 1] = 9;
cp[ 2] = 9;
cp[40] = 9;
cp[41] = 9;
cp[42] = 9;
score_inc(0, 5);
}
}
}
void brick_animate(void)
{
char n = numFlashingBricks[0];
for(char i=0; i<n; i++)
{
char x = flashingBricks[i] & 0xff;
char y = flashingBricks[i] >> 8;
char * cp = Color + 40 * y + x;
cp[ 0] = 15;
cp[ 1] = 15;
cp[ 2] = 15;
cp[40] = 15;
cp[41] = 15;
cp[42] = 15;
char * sp = Screen + 40 * (y - 1) + (x - 1);
char ch = 96 + (x & 1) + 2 * (y & 1);
if (sp[ 0] >= 128)
sp[41] = ch | 4;
else
sp[41] = ch;
if (sp[ 1] >= 128)
sp[42] = (ch ^ 1) | 4;
else
sp[42] = (ch ^ 1);
if (sp[ 2] >= 128)
sp[43] = ch | 4;
else
sp[43] = ch;
if (sp[40] >= 128)
sp[81] = (ch ^ 2) | 4;
else
sp[81] = (ch ^ 2);
sp[82] = (ch ^ 3);
sp[83] = (ch ^ 2);
if (sp[84] < 128)
sp[84] = (ch ^ 3);
if (sp[122] < 128)
sp[122] = (ch ^ 1);
if (sp[123] < 128)
sp[123] = ch;
if (sp[124] < 128)
sp[124] = (ch ^ 1);
}
for(char i=0; i<3; i++)
numFlashingBricks[i] = numFlashingBricks[i + 1] - n;
numFlashingBricks[3] = numFlashingBricks[2];
for(char i=0; i<numFlashingBricks[3]; i++)
flashingBricks[i] = flashingBricks[i + n];
}
struct Ball
{
char index;
bool active;
int sx, sy, vx, vy;
};
// using 10.6 bit fixed point math
#define BALL_INT(x) ((x) >> 6)
#define BALL_COORD(x, f) (((x) << 6) + f)
void ball_init(Ball * ball, char index, int sx, int sy, int vx, int vy)
{
ball->index = index;
ball->active = true;
ball->sx = sx;
ball->sy = sy;
ball->vx = vx;
ball->vy = vy;
int ix = BALL_INT(ball->sx) + 24, iy = BALL_INT(ball->sy) + 50;
spr_set(2 * index + 2, true, ix, iy, 97, 0, false, false, false);
spr_set(2 * index + 3, true, ix, iy, 96, 15, true, false, false);
}
void ball_lost(Ball * ball)
{
ball->active = false;
spr_show(2 * ball->index + 2, false);
spr_show(2 * ball->index + 3, false);
return;
}
#define COL_00 1
#define COL_01 2
#define COL_10 4
#define COL_11 8
int paddlex, paddlevx;
char sound_index;
unsigned sound_freq;
void sound_trigger(unsigned freq)
{
sound_freq = freq;
if (sound_index == 0)
sound_index = 3;
else if (sound_index > 6)
sound_index = 1;
}
void sound_loop(void)
{
switch (sound_index)
{
case 0:
break;
case 1:
case 18:
sid.voices[0].ctrl = 0;
sid.voices[0].attdec = 0;
sid.voices[0].susrel = 0;
sound_index++;
break;
case 2:
case 19:
sid.voices[0].ctrl = SID_CTRL_TEST;
sound_index++;
break;
case 3:
sid.voices[0].freq = sound_freq;
sid.voices[0].attdec = SID_ATK_2 | SID_DKY_6;
sid.voices[0].susrel = SID_DKY_300 | 0xf0;
sid.voices[0].pwm = 0x800;
sid.voices[0].ctrl = SID_CTRL_RECT | SID_CTRL_GATE | SID_CTRL_NOISE;
sound_index++;
break;
case 4:
case 5:
sound_index++;
break;
case 6:
sound_index++;
sid.voices[0].ctrl = SID_CTRL_RECT;
break;
case 20:
sound_index = 0;
break;
default:
sound_index++;
}
}
void ball_loop(Ball * ball)
{
if (!ball->active)
return;
ball->sx += ball->vx;
ball->sy += ball->vy;
bool mirrorX = false, mirrorY = false;
int ix = BALL_INT(ball->sx), iy = BALL_INT(ball->sy);
int px = BALL_INT(paddlex);
if (ix + 6 > 320 || ix < 0)
{
mirrorX = true;
sound_trigger(NOTE_D(6));
}
if (iy < 0)
{
mirrorY = true;
sound_trigger(NOTE_D(6));
}
else if (iy >= 200)
{
ball_lost(ball);
return;
}
if (iy + 6 > 190 && iy < 190)
{
if (ix + 5 >= px && ix < px + 48)
{
mirrorY = true;
if (ix < px && ball->vx > 0)
{
mirrorX = true;
}
else if (ix + 6 >= px + 48 && ball->vx < 0)
{
mirrorX = true;
}
else
{
ball->vx = (ball->vx * 6 + paddlevx + 4) >> 3;
}
sound_trigger(NOTE_D(7));
}
}
int x0 = ix >> 3;
int y0 = iy >> 3;
int x1 = (ix + 5) >> 3;
int y1 = (iy + 5) >> 3;
if (x0 >= 0 && x1 < 40 && y0 >= 0 && y1 < 24)
{
char col = 0;
bool hit = false;
if (Screen[40 * y0 + x0] >= 128) col |= COL_00;
if (Screen[40 * y0 + x1] >= 128) col |= COL_01;
if (Screen[40 * y1 + x0] >= 128) col |= COL_10;
if (Screen[40 * y1 + x1] >= 128) col |= COL_11;
if (ball->vx < 0 && ((col & (COL_00 | COL_01)) == COL_00) || ((col & (COL_10 | COL_11)) == COL_10))
{
mirrorX = true;
hit = true;
}
else if (ball->vx > 0 && ((col & (COL_00 | COL_01)) == COL_01) || ((col & (COL_10 | COL_11)) == COL_11))
{
mirrorX = true;
hit = true;
}
if (ball->vy < 0 && ((col & (COL_00 | COL_10)) == COL_00) || ((col & (COL_01 | COL_11)) == COL_01))
{
mirrorY = true;
hit = true;
}
else if (ball->vy > 0 && ((col & (COL_00 | COL_10)) == COL_10) || ((col & (COL_01 | COL_11)) == COL_11))
{
mirrorY = true;
hit = true;
}
if (col)
{
brick_hit(x0, y0);
brick_hit(x1, y0);
brick_hit(x0, y1);
brick_hit(x1, y1);
}
if (hit)
{
sound_trigger(NOTE_D(8));
}
}
if (mirrorY)
{
ball->vy = - ball->vy;
ball->sy += ball->vy;
}
if (mirrorX)
{
ball->vx = - ball->vx;
ball->sx += ball->vx;
}
}
void ball_move(Ball * ball)
{
int ix = BALL_INT(ball->sx) + 24, iy = BALL_INT(ball->sy) + 50;
spr_move(2 * ball->index + 2, ix, iy);
spr_move(2 * ball->index + 3, ix, iy);
}
enum GameState
{
GS_READY, // Getting ready
GS_BALL_LOCKED, // The ball is locked on the paddle
GS_PLAYING, // Playing the game
GS_BALL_DROPPED, // The last ball has been dropped
GS_GAME_OVER
};
struct Game
{
GameState state;
Ball balls[3];
char count;
} TheGame;
void paddle_init(void)
{
paddlevx = 0;
paddlex = BALL_COORD(160, 0);
spr_set(0, true, 24 + BALL_INT(paddlex), 240, 99, 0, false, true, false);
spr_set(1, true, 24 + BALL_INT(paddlex), 240, 98, 15, true, true, false);
}
void paddle_control(void)
{
joy_poll(0);
if (joyx[0] == 0)
{
if (paddlevx < 0)
paddlevx = (paddlevx + 1) >> 1;
else
paddlevx >>= 1;
}
else
{
paddlevx += joyx[0] * 8;
if (paddlevx >= 256)
paddlevx = 256;
else if (paddlevx < -256)
paddlevx = -256;
}
paddlex += paddlevx;
if (paddlex < BALL_COORD(-4, 0) || paddlex > BALL_COORD(320 - 48 + 4, 0))
{
paddlevx = -paddlevx;
paddlex += paddlevx;
}
}
void paddle_move(void)
{
spr_move(0, 24 + BALL_INT(paddlex), 240);
spr_move(1, 24 + BALL_INT(paddlex), 240);
}
void game_state(GameState state)
{
// Set new state
TheGame.state = state;
switch (state)
{
case GS_READY:
brick_init();
paddle_init();
TheGame.count = 120;
break;
case GS_BALL_LOCKED:
ball_init(TheGame.balls + 0, 0, paddlex + BALL_COORD(22, 0), BALL_COORD(184, 0), BALL_COORD(0, 0), BALL_COORD(0, 0));
ball_init(TheGame.balls + 1, 1, paddlex + BALL_COORD(22, 0), BALL_COORD(184, 0), BALL_COORD(0, 0), BALL_COORD(0, 0));
ball_init(TheGame.balls + 2, 2, paddlex + BALL_COORD(22, 0), BALL_COORD(184, 0), BALL_COORD(0, 0), BALL_COORD(0, 0));
break;
case GS_PLAYING:
TheGame.balls[0].vy = BALL_COORD(-2, 32);
TheGame.balls[0].vx = paddlevx >> 2;
TheGame.balls[1].vy = BALL_COORD(-2, 16);
TheGame.balls[1].vx = (paddlevx >> 2) - 16;
TheGame.balls[2].vy = BALL_COORD(-2, 16);
TheGame.balls[2].vx = (paddlevx >> 2) + 16;
break;
case GS_BALL_DROPPED:
TheGame.count = 60;
break;
case GS_GAME_OVER:
TheGame.count = 120;
break;
}
}
void game_loop()
{
switch (TheGame.state)
{
case GS_READY:
paddle_control();
if (!--TheGame.count)
game_state(GS_BALL_LOCKED);
break;
case GS_BALL_LOCKED:
paddle_control();
TheGame.balls[0].sx = paddlex + BALL_COORD(22, 0);
TheGame.balls[1].sx = paddlex + BALL_COORD(22, 0);
TheGame.balls[2].sx = paddlex + BALL_COORD(22, 0);
if (joyb[0])
game_state(GS_PLAYING);
break;
case GS_PLAYING:
paddle_control();
// vic.color_border++;
for(char i=0; i<3; i++)
ball_loop(TheGame.balls + i);
for(char i=0; i<3; i++)
ball_loop(TheGame.balls + i);
// vic.color_border--;
if (!(TheGame.balls[0].active || TheGame.balls[1].active || TheGame.balls[2].active))
game_state(GS_BALL_DROPPED);
break;
case GS_BALL_DROPPED:
paddle_control();
if (!--TheGame.count)
game_state(GS_BALL_LOCKED);
break;
case GS_GAME_OVER:
if (!--TheGame.count)
game_state(GS_READY);
break;
}
}
int main(void)
{
mmap_trampoline();
// Install character set
mmap_set(MMAP_RAM);
memcpy(Font, charset, 2048);
memcpy(Sprites, spriteset, 256);
mmap_set(MMAP_NO_BASIC);
// Switch screen
vic_setmode(VICM_TEXT_MC, Screen, Font);
spr_init(Screen);
// Change colors
vic.color_border = VCOL_BLACK;
vic.color_back = VCOL_BLACK;
vic.color_back1 = VCOL_WHITE;
vic.color_back2 = VCOL_DARK_GREY;
vic.spr_mcolor0 = VCOL_DARK_GREY;
vic.spr_mcolor1 = VCOL_WHITE;
memset(Screen, 96, 1000);
memset(Color, 15, 1000);
game_state(GS_READY);
sid.fmodevol = 15;
for(;;)
{
brick_animate();
game_loop();
sound_loop();
vic_waitFrame();
for(char j=0; j<3; j++)
ball_move(TheGame.balls + j);
paddle_move();
}
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
../../bin/oscar64 snake.c
../../bin/oscar64 lander.c -n
../../bin/oscar64 maze3d.c -n
../../bin/oscar64 missile.c -O3 -n
../../bin/oscar64 breakout.c -n
../../bin/oscar64 connectfour.c -n
../../bin/oscar64 hscrollshmup.c -O2 -n
+819
View File
@@ -0,0 +1,819 @@
#include <c64/joystick.h>
#include <c64/vic.h>
#include <c64/sprites.h>
#include <c64/memmap.h>
#include <c64/rasterirq.h>
#include <c64/sid.h>
#include <c64/charwin.h>
#include <c64/types.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
// Include charset and sprite resources
char charset[2048] = {
#embed "../resources/connect4chars.bin"
};
char spriteset[2048] = {
#embed "../resources/connect4sprites.bin"
};
// Address ov video data
byte * const Screen = (byte *)0xc800;
byte * const Font = (byte *)0xd000;
byte * const Color = (byte *)0xd800;
byte * const Sprites = (byte *)0xd800;
// Values for player 1 pieces and player 2 pieces.
// The values 1 and 5 are selected so that the sum of the
// values in a row of four will add up to a unique value
// in the range of 0..24 for ranking
#define PLAYER1_INC 1
#define PLAYER2_INC 5
// Current state of the board
struct Board
{
char fcols[48]; // Pieces in the 6x7 grid using 48 to have a multiplier of 8
char ffree[7]; // Number of free places in each column
} board;
enum GameState
{
GS_READY, // Getting ready
GS_PLAYER_MOVE, // The players move
GS_COMPUTER_MOVE, // The computers move
GS_PLAYER_WIN, // The player wins
GS_COMPUTER_WIN, // The computer wins
GS_GAME_OVER // No more moves
};
// Draw the board into the CharWin using the small
// character set
void board_draw(CharWin * cwin)
{
for(char y=0; y<6; y++)
{
for(char x=0; x<7; x++)
{
if (board.fcols[8 * y + x] == PLAYER1_INC)
cwin_putat_char_raw(cwin, x, y, 82, 10);
else if (board.fcols[8 * y + x] == PLAYER2_INC)
cwin_putat_char_raw(cwin, x, y, 82, 15);
else
cwin_putat_char_raw(cwin, x, y, 82, 8);
}
// Right most column
cwin_putat_char_raw(cwin, 7, y, 83, 8);
}
}
// Draw a big piece or place with the given color, the
// color 0 denotes an empty place. Empty places use different
// tiles to allow sprite priority to obscure the falling pieces
void board_draw_item(CharWin * cwin, char x, char y, char c)
{
char cx = x * 3 + 1, cy = y * 3 + 2;
if (c)
{
cwin_putat_char_raw(cwin, cx + 0, cy + 0, 73, c);
cwin_putat_char_raw(cwin, cx + 1, cy + 0, 74, c);
cwin_putat_char_raw(cwin, cx + 2, cy + 0, 75, c);
cwin_putat_char_raw(cwin, cx + 0, cy + 1, 76, c);
cwin_putat_char_raw(cwin, cx + 1, cy + 1, 77, c);
cwin_putat_char_raw(cwin, cx + 2, cy + 1, 78, c);
cwin_putat_char_raw(cwin, cx + 0, cy + 2, 79, c);
cwin_putat_char_raw(cwin, cx + 1, cy + 2, 80, c);
cwin_putat_char_raw(cwin, cx + 2, cy + 2, 81, c);
}
else
{
cwin_putat_char_raw(cwin, cx + 0, cy + 0, 64, 14);
cwin_putat_char_raw(cwin, cx + 1, cy + 0, 65, 14);
cwin_putat_char_raw(cwin, cx + 2, cy + 0, 66, 14);
cwin_putat_char_raw(cwin, cx + 0, cy + 1, 67, 14);
cwin_putat_char_raw(cwin, cx + 1, cy + 1, 68, 14);
cwin_putat_char_raw(cwin, cx + 2, cy + 1, 69, 14);
cwin_putat_char_raw(cwin, cx + 0, cy + 2, 70, 14);
cwin_putat_char_raw(cwin, cx + 1, cy + 2, 71, 14);
cwin_putat_char_raw(cwin, cx + 2, cy + 2, 72, 14);
}
}
// Draw the big board
void board_draw_main(CharWin * cwin)
{
for(char y=0; y<6; y++)
{
for(char x=0; x<7; x++)
{
if (board.fcols[8 * y + x] == PLAYER1_INC)
board_draw_item(cwin, x, y, 10);
else if (board.fcols[8 * y + x] == PLAYER2_INC)
board_draw_item(cwin, x, y, 15);
else
board_draw_item(cwin, x, y, 0);
}
}
}
// Draw the decoration of the big board
void board_init_main(CharWin * cwin)
{
// Frame around the board
cwin_putat_char_raw(cwin, 0, 1, 84, 14);
cwin_fill_rect_raw(cwin, 1, 1, 21, 1, 85, 14);
cwin_putat_char_raw(cwin, 22, 1, 86, 14);
cwin_fill_rect_raw(cwin, 0, 2, 1, 18, 87, 14);
cwin_fill_rect_raw(cwin, 22, 2, 1, 18, 88, 14);
cwin_putat_char_raw(cwin, 0, 20, 89, 14);
cwin_fill_rect_raw(cwin, 1, 20, 21, 1, 90, 14);
cwin_putat_char_raw(cwin, 22, 20, 91, 14);
// Fields in the board
for(char x=0; x<7; x++)
cwin_putat_char_raw(cwin, 3 * x + 2, 0, '1' + x, 1);
board_draw_main(cwin);
}
// Play animation of a dropped piece
void item_drop_anim(CharWin * cwin, char x, char y, char c)
{
// Initial position
int ix = (cwin->sx + 3 * x + 1) * 8 + 24, iy = (cwin->sy + 2) * 8 + 20;
// Show sprite at start position
spr_set(0, true, ix, iy, 97, c, true, false, false);
// Set sprite priority to be behind background
vic.spr_priority = 0x01;
// Speed and target position, using four fractional bits
int vy = 0, aiy = iy * 16, ty = ((cwin->sy + y * 3 + 2) * 8 + 50) * 16;
// Bounce three times back when reaching bottom
char bounce = 3;
// Loop through the bounces
while (bounce > 0)
{
// Let gravity do its thing of accelerating
vy += 3;
// Add vertical velocity to position
aiy += vy;
// Reached the bottom yet?
if (aiy > ty)
{
// Reflect position
aiy = 2 * ty - aiy;
// Reflect speed
vy = - vy * 5 >> 4;
// One bounce down
bounce--;
}
// Move sprite and wait for display
spr_move(0, ix, aiy >> 4);
vic_waitFrame();
}
}
// Play column selection animation
void column_select_anim(CharWin * cwin, char x0, char x1, char c)
{
// Start position
int ix = (cwin->sx + 3 * x0 + 1) * 8 + 24, iy = (cwin->sy + 2) * 8 + 20;
// Target position
int tx = (cwin->sx + 3 * x1 + 1) * 8 + 24;
// Show sprite at start position
spr_set(0, true, ix, iy, 97, c, true, false, false);
// Set sprite priority to be behind background
vic.spr_priority = 0x01;
// Not at target position already?
if (ix != tx)
{
// Eight frames for movement
for(int i=1; i<=8; i++)
{
vic_waitFrame();
// Move sprite along path
spr_move(0, (ix * (8 - i) + tx * i) >> 3, iy);
}
}
}
// Initialize the board to empty
void board_init(void)
{
// Column has six free slots
for(char x=0; x<7; x++)
board.ffree[x] = 6;
// Clear all slots
for(char i=0; i<48; i++)
board.fcols[i] = 0;
}
// Drop one piece of player p down column x
inline bool board_drop(char x, bool p)
{
// Check for free space
if (board.ffree[x])
{
// Fill one slot
char y = --(board.ffree[x]);
board.fcols[8 * y + x] = p ? PLAYER2_INC : PLAYER1_INC;
// Success
return true;
}
return false;
}
// Remove the top piece from column x
inline void board_undrop(char x)
{
// Free one slot
char y = (board.ffree[x])++;
board.fcols[8 * y + x] = 0x00;
}
// Score for rows with 0, 1, 2, and 3 elements of same color
static const int score[5] = {0, 1, 8, 128, 10000};
// Score index is calculated (25 * rv + 5 * p1 + p2) with rv the
// value range of the row, p1 and p2 number of pieces from player 1 or 2
int fscore[125];
// Indices of the board positions of four slots of each of the 69
// 4 slot rows in the board. The fifth value is the value range
// of the row
char frows[5][69];
#pragma align(fscore, 256)
// Tables for opening library for computer move 1, 2, 3 and 4
const char open1 = 3;
const char open2[4 * 7] =
{
4, 3, 3, 3, 4, 3, 3, 3, 5, 3, 3, 4, 3, 3, 3, 3, 2, 3, 2, 2, 2, 4, 2, 4, 3, 2, 4, 2
};
const char open3[4 * 7 * 7] = {
0, 5, 2, 2, 5, 3, 2, 5, 4, 2, 4, 3, 3, 5, 2, 2, 3, 2, 3, 2, 2, 4, 5, 2, 4, 4, 3, 2,
3, 3, 3, 3, 3, 3, 4, 1, 3, 2, 5, 3, 2, 1, 2, 5, 2, 2, 4, 1, 4, 5, 4, 2, 4, 3, 3, 5,
4, 1, 3, 4, 4, 4, 3, 2, 1, 3, 2, 3, 2, 3, 5, 5, 1, 5, 4, 3, 3, 3, 4, 3, 3, 5, 3, 3,
3, 5, 2, 3, 4, 1, 3, 5, 4, 3, 1, 4, 3, 5, 2, 2, 3, 2, 3, 2, 2, 2, 1, 3, 2, 3, 2, 3,
3, 1, 3, 2, 2, 3, 3, 2, 1, 3, 2, 2, 2, 2, 3, 3, 3, 2, 1, 3, 3, 3, 3, 1, 3, 3, 2, 3,
2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2, 3, 4, 3, 2, 4, 3, 2, 2, 2, 2, 1, 0, 2, 4, 3, 4, 4,
4, 4, 1, 2, 5, 2, 2, 2, 2, 3, 2, 4, 6, 5, 4, 4, 4, 4, 3, 2, 4, 3, 2, 3, 4, 5, 4, 3,
};
const char open4[4 * 7 * 7 * 7] = {
2, 5, 2, 2, 5, 3, 2, 2, 2, 6, 2, 2, 2, 2, 0, 4, 4, 3, 2, 3, 3, 5, 5, 5, 5, 5, 1, 1,
2, 2, 6, 2, 2, 2, 2, 0, 4, 4, 4, 3, 5, 4, 1, 5, 1, 1, 1, 1, 1, 0, 4, 2, 4, 3, 4, 5,
5, 1, 4, 5, 5, 3, 2, 3, 3, 1, 1, 1, 1, 3, 5, 5, 4, 5, 5, 4, 4, 3, 3, 3, 1, 3, 3, 3,
3, 3, 3, 1, 3, 3, 3, 5, 4, 2, 5, 3, 1, 4, 0, 3, 6, 2, 3, 3, 3, 3, 3, 1, 1, 1, 1, 3,
3, 3, 3, 2, 3, 3, 3, 2, 1, 6, 2, 4, 5, 2, 3, 3, 3, 2, 3, 3, 3, 3, 1, 5, 5, 3, 3, 3,
3, 3, 0, 2, 3, 3, 3, 0, 5, 2, 2, 5, 1, 2, 4, 4, 2, 4, 5, 4, 2, 2, 2, 3, 2, 2, 2, 2,
2, 5, 5, 2, 2, 1, 2, 4, 3, 4, 4, 3, 3, 4, 1, 3, 2, 1, 4, 4, 1, 4, 5, 4, 4, 4, 2, 4,
0, 3, 3, 4, 3, 3, 3, 3, 3, 3, 1, 3, 5, 3, 3, 3, 3, 2, 2, 4, 3, 4, 3, 4, 4, 3, 3, 4,
3, 3, 2, 3, 3, 5, 6, 3, 5, 4, 5, 5, 3, 3, 3, 3, 2, 3, 3, 3, 5, 0, 5, 3, 4, 4, 3, 2,
3, 3, 3, 1, 3, 3, 3, 3, 1, 5, 5, 3, 3, 3, 3, 3, 2, 1, 4, 3, 1, 3, 3, 3, 4, 3, 3, 3,
2, 2, 3, 2, 5, 5, 4, 2, 5, 3, 1, 4, 2, 1, 0, 2, 4, 4, 3, 2, 4, 5, 4, 2, 5, 3, 1, 4,
3, 3, 0, 2, 3, 3, 3, 4, 2, 4, 4, 2, 2, 4, 3, 3, 3, 4, 6, 3, 3, 2, 5, 3, 1, 4, 2, 1,
2, 2, 3, 2, 2, 4, 6, 0, 4, 2, 4, 3, 4, 5, 5, 1, 4, 5, 5, 3, 2, 3, 3, 1, 1, 1, 1, 3,
5, 5, 4, 5, 5, 4, 4, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 5, 4, 2, 5, 3, 1, 4,
2, 2, 6, 2, 2, 2, 2, 4, 4, 3, 4, 4, 4, 3, 4, 1, 3, 5, 3, 3, 3, 2, 2, 6, 2, 2, 2, 2,
5, 1, 3, 3, 5, 4, 3, 2, 2, 6, 2, 2, 2, 2, 4, 1, 3, 5, 3, 1, 3, 3, 3, 1, 1, 1, 1, 3,
6, 2, 3, 1, 4, 5, 4, 3, 3, 3, 2, 3, 3, 3, 1, 2, 3, 1, 4, 1, 1, 3, 3, 3, 4, 3, 2, 3,
1, 3, 1, 1, 4, 2, 1, 3, 3, 3, 2, 3, 3, 3, 4, 4, 2, 4, 5, 4, 2, 4, 1, 6, 4, 4, 4, 2,
1, 3, 2, 4, 3, 1, 1, 4, 4, 4, 4, 4, 4, 2, 3, 3, 4, 4, 3, 3, 4, 3, 5, 3, 1, 3, 1, 3,
5, 2, 2, 5, 4, 3, 5, 3, 3, 3, 1, 3, 5, 3, 3, 1, 4, 4, 5, 3, 3, 3, 1, 3, 2, 2, 2, 3,
3, 3, 4, 4, 3, 3, 4, 3, 5, 3, 3, 5, 5, 3, 5, 4, 2, 5, 5, 3, 5, 3, 3, 3, 1, 1, 5, 3,
3, 3, 3, 1, 3, 3, 3, 5, 1, 1, 3, 4, 3, 3, 1, 3, 1, 1, 4, 2, 1, 5, 5, 2, 1, 4, 1, 1,
5, 4, 2, 5, 5, 3, 5, 3, 3, 2, 3, 5, 5, 1, 3, 3, 3, 5, 3, 3, 3, 5, 4, 2, 5, 3, 1, 4,
2, 1, 1, 4, 3, 4, 4, 3, 3, 3, 2, 3, 3, 3, 5, 3, 2, 5, 4, 3, 3, 3, 3, 3, 1, 1, 5, 3,
3, 3, 3, 5, 3, 3, 3, 4, 3, 2, 2, 3, 1, 6, 0, 3, 6, 2, 3, 3, 3, 3, 3, 1, 1, 1, 1, 3,
3, 3, 3, 2, 3, 3, 3, 2, 1, 6, 2, 4, 5, 2, 3, 3, 3, 2, 3, 3, 3, 3, 1, 5, 5, 3, 3, 3,
3, 3, 0, 2, 3, 3, 3, 3, 3, 1, 1, 1, 1, 3, 6, 2, 3, 1, 4, 5, 4, 3, 3, 3, 2, 3, 3, 3,
1, 2, 3, 1, 4, 1, 1, 3, 3, 3, 4, 3, 2, 3, 1, 3, 1, 1, 4, 2, 1, 3, 3, 3, 2, 3, 3, 3,
3, 3, 3, 4, 3, 3, 3, 2, 3, 1, 3, 0, 1, 1, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 2, 2, 3,
4, 4, 4, 2, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2, 2, 2, 2,
1, 3, 2, 4, 3, 1, 1, 0, 1, 2, 2, 4, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 2, 2, 3, 3, 2, 3, 3, 2, 2, 3, 2, 3, 1, 3, 4, 3, 3, 3, 1, 1, 4, 4, 2, 4, 2,
3, 4, 3, 4, 3, 4, 4, 3, 2, 3, 2, 3, 3, 3, 1, 2, 2, 2, 4, 4, 2, 3, 4, 4, 4, 3, 5, 3,
3, 2, 4, 4, 3, 3, 3, 3, 1, 5, 5, 3, 3, 3, 1, 3, 1, 1, 4, 2, 1, 3, 1, 1, 3, 3, 1, 3,
2, 3, 3, 2, 2, 3, 3, 3, 4, 4, 4, 3, 5, 3, 3, 3, 1, 2, 2, 5, 3, 3, 1, 3, 5, 3, 3, 3,
1, 3, 3, 3, 4, 3, 3, 3, 3, 1, 1, 2, 1, 3, 0, 1, 3, 3, 4, 3, 3, 2, 3, 3, 2, 2, 3, 2,
3, 2, 4, 4, 3, 3, 3, 3, 1, 3, 5, 3, 3, 3, 3, 3, 3, 2, 3, 3, 6, 0, 2, 1, 2, 3, 4, 4,
4, 1, 3, 3, 4, 4, 2, 4, 3, 2, 4, 3, 3, 4, 3, 3, 2, 4, 4, 4, 3, 3, 2, 1, 4, 3, 3, 3,
4, 2, 1, 4, 5, 4, 2, 4, 2, 1, 2, 3, 4, 4, 2, 2, 1, 2, 1, 2, 2, 1, 1, 3, 3, 3, 5, 1,
2, 5, 3, 2, 5, 3, 3, 2, 3, 1, 1, 1, 6, 2, 1, 4, 4, 1, 4, 6, 5, 2, 2, 1, 6, 6, 2, 4,
2, 2, 1, 2, 5, 4, 2, 4, 3, 2, 4, 3, 3, 4, 4, 3, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 3, 3,
1, 0, 2, 2, 4, 5, 2, 1, 0, 3, 1, 3, 1, 3, 1, 0, 2, 5, 2, 2, 5, 1, 0, 3, 2, 2, 5, 2,
2, 2, 1, 4, 4, 4, 2, 2, 4, 0, 2, 4, 2, 4, 5, 4, 2, 1, 5, 4, 1, 2, 1, 2, 2, 2, 4, 2,
5, 2, 1, 5, 4, 2, 1, 2, 4, 2, 4, 6, 2, 4, 4, 2, 2, 2, 5, 4, 4, 4, 1, 4, 2, 3, 6, 5,
1, 4, 4, 1, 4, 6, 5, 3, 5, 3, 5, 3, 6, 5, 2, 1, 2, 4, 4, 6, 5, 3, 3, 3, 3, 3, 6, 5,
5, 5, 3, 3, 3, 3, 2, 2, 3, 3, 2, 4, 3, 2, 4, 2, 1, 4, 5, 4, 2, 2, 4, 0, 0, 5, 4, 2,
1, 0, 2, 5, 2, 2, 5, 4, 0, 5, 5, 5, 3, 4, 3, 3, 1, 4, 3, 1, 2, 5, 1, 3, 3, 3, 5, 5,
2, 2, 5, 4, 5, 4, 4, 2, 2, 3, 4, 5, 4, 2, 2, 2, 1, 2, 5, 4, 2, 3, 3, 3, 2, 5, 4, 3,
3, 2, 2, 2, 4, 3, 3, 2, 3, 3, 2, 4, 3, 2, 4, 2, 2, 3, 3, 5, 2, 2, 2, 3, 4, 5, 4, 6,
};
// Init the ai tables
void ai_init(void)
{
// Loop over 5 value ranges, and 0 to 4 pieces of each player
// in a row
for(char k=0; k<5; k++)
{
for(char i=0; i<5; i++)
{
for(char j=0; j<5; j++)
{
if (i && j)
fscore[25 * k + PLAYER2_INC * i + j] = 0;
else if (i == 4 || j == 4)
fscore[25 * k + PLAYER2_INC * i + j] = score[i] - score[j];
else
fscore[25 * k + PLAYER2_INC * i + j] = (score[i] - score[j]) * (1 + k);
}
}
}
// Create the indices of all 69 rows
char p = 0;
// Vertical rows
for(char x=0; x<7; x++)
{
for(char y=0; y<3; y++)
{
frows[0][p] = x + 8 * y;
frows[1][p] = x + 8 * y + 8;
frows[2][p] = x + 8 * y + 16;
frows[3][p] = x + 8 * y + 24;
frows[4][p] = 25 * (y + 1);
p++;
}
}
for(char x=0; x<4; x++)
{
// Horizontal rows
for(char y=0; y<6; y++)
{
frows[0][p] = x + 8 * y;
frows[1][p] = x + 8 * y + 1;
frows[2][p] = x + 8 * y + 2;
frows[3][p] = x + 8 * y + 3;
frows[4][p] = y > 0 ? 25 * (y - 1) : 0;
p++;
}
// Diagonal down rows
for(char y=0; y<3; y++)
{
frows[0][p] = x + 8 * y;
frows[1][p] = x + 8 * y + 9;
frows[2][p] = x + 8 * y + 18;
frows[3][p] = x + 8 * y + 27;
frows[4][p] = 25 * (y + 1);
p++;
}
// Diagonal up rows
for(char y=3; y<6; y++)
{
frows[0][p] = x + 8 * y;
frows[1][p] = x + 8 * y - 7;
frows[2][p] = x + 8 * y - 14;
frows[3][p] = x + 8 * y - 21;
frows[4][p] = 25 * (y - 2);
p++;
}
}
}
// Evaluate the current board state for the player
int board_eval(bool player)
{
int score = 0;
// Loop through all rows
for(char r=0; r<69; r++)
{
// Build score index for row
char sum =
board.fcols[frows[0][r]] +
board.fcols[frows[1][r]] +
board.fcols[frows[2][r]] +
board.fcols[frows[3][r]] +
frows[4][r];
// Help compiler to avoid two byte pointer arithmetic
__assume(sum < 128);
// Add score to board score
score += fscore[sum];
}
// Check if there was a row with four winning pieces and
// normalize to +/- 32000 then
if (score < -8192)
score = -32000;
else if (score >= 8192)
score = 32000;
// Invert score for other player
return player ? score : -score;
}
CharWin cwt, cws;
CharWin cw, cwm;
char buff[20];
static const char optx[7] = {3, 2, 4, 1, 5, 0, 6};
// Find a good move for the player using alpha/beta pruning
// see: https://en.wikipedia.org/wiki/Alpha-beta_pruning
int board_check(char level, int alpha, int beta, bool player)
{
int best = alpha;
bool checked = false;
// Current score to cutof early if clear win condition
int val = board_eval(player) + level;
// Best move
char zx = 0;
// Check for end of search
if (level < 5 && val < 5000 && val > -5000)
{
// Update current check display at level 3
if (level == 3)
{
board_draw(&cwt);
itoa(val, buff, 10);
cwin_fill_rect(&cwt, 0, 6, 7, 1, ' ', 1);
cwin_putat_string(&cwt, 0, 6, buff, 1);
}
// Check all seven columns
for(char i=0; i<7; i++)
{
// Start check in the center, due to higher value of
// pieces there
char ix = optx[i];
// Try to drop a piece
if (board_drop(ix, player))
{
// We still have a move
checked = true;
// Check score of position
int score = - board_check(level + 1, -beta, -best, !player);
// Better than what we have so far
if (score > best)
{
// Remember
best = score;
zx = ix;
// Update best move if on level zero
if (level == 0)
{
board_draw(&cw);
itoa(best, buff, 10);
cwin_fill_rect(&cw, 0, 6, 7, 1, ' ', 1);
cwin_putat_string(&cw, 0, 6, buff, 1);
}
// Check for beta pruning
if (best > beta)
{
board_undrop(ix);
break;
}
}
// Undo move
board_undrop(ix);
}
}
}
// Return new position if first move level
if (level == 0)
return zx;
else if (checked)
return best;
else
return val;
}
// Return a move from the opening library if available
char board_opening(char step, char * moves)
{
switch (step)
{
case 1:
return open1;
case 2:
if (moves[0] < 4)
return open2[moves[0] * 7 + moves[1]];
else
return 6 - open2[(6 - moves[0]) * 7 + (6 - moves[1])];
case 3:
if (moves[0] < 4)
return open3[moves[0] * 49 + moves[1] * 7 + moves[2]];
else
return 6 - open3[(6 - moves[0]) * 49 + (6 - moves[1]) * 7 + (6 - moves[2])];
case 4:
if (moves[0] < 4)
return open4[moves[0] * 343 + moves[1] * 49 + moves[2] * 7 + moves[3]];
else
return 6 - open4[(6 - moves[0]) * 343 + (6 - moves[1]) * 49 + (6 - moves[2]) * 7 + (6 - moves[3])];
default:
return 0xff;
}
}
// Current state of the game
struct Game
{
GameState state; // State
char count; // Auto continue counter
char posx; // Column osition of new piece
char step; // Number of player moves
char moves[21]; // Pieces placed by player
} TheGame;
// Set new game state
void game_state(GameState state)
{
// Set new state
TheGame.state = state;
// Clear status line
cwin_fill_rect(&cws, 0, 0, 40, 1, ' ', 1);
switch (state)
{
case GS_READY:
// Start play in one second
TheGame.count = 60;
TheGame.step = 0;
// Clear the board
board_init();
board_init_main(&cwm);
break;
case GS_PLAYER_MOVE:
// Place selection sprite in center
TheGame.posx = 3;
column_select_anim(&cwm, 3, 3, 7);
cwin_putat_string(&cws, 0, 0, P"PLAYER MOVE", 7);
break;
case GS_COMPUTER_MOVE:
cwin_putat_string(&cws, 0, 0, P"COMPUTER MOVE", 2);
break;
case GS_PLAYER_WIN:
cwin_putat_string(&cws, 0, 0, P"PLAYER WINS", 7);
// Continue in 4 seconds
TheGame.count = 240;
break;
case GS_COMPUTER_WIN:
cwin_putat_string(&cws, 0, 0, P"COMPUTER WINS", 2);
// Continue in 4 seconds
TheGame.count = 240;
break;
case GS_GAME_OVER:
cwin_putat_string(&cws, 0, 0, P"NO MORE MOVES", 1);
// Continue in 4 seconds
TheGame.count = 240;
break;
}
}
// Main game loop
void game_loop()
{
char bx = 0xff, cx;
switch (TheGame.state)
{
case GS_READY:
if (!--TheGame.count)
game_state(GS_PLAYER_MOVE);
break;
case GS_PLAYER_MOVE:
// Current selection
cx = TheGame.posx;
// Check for key pressed
if (kbhit())
{
// Get key
char ch = getch();
// Numbers 1 to 7 drop immediate
if (ch >= '1' && ch <= '7')
bx = cx = ch - '1';
}
else
{
// Check Joystick
joy_poll(0);
// Move cursor
if (joyx[0] < 0 && cx > 0)
cx--;
else if (joyx[0] > 0 && cx < 6)
cx++;
else if(joyb[0])
bx = cx;
}
// Move selection piece
column_select_anim(&cwm, TheGame.posx, cx, 7);
TheGame.posx = cx;
if (bx != 0xff)
{
// Drop piece into board
if (board_drop(bx, true))
{
// Remember move
TheGame.moves[TheGame.step++] = bx;
// Play drop animation
item_drop_anim(&cwm, bx, board.ffree[bx], 7);
// Show new state of the board
board_draw_main(&cwm);
spr_show(0, false);
// Check for win condition
if (board_eval(true) == 32000)
game_state(GS_PLAYER_WIN);
else
game_state(GS_COMPUTER_MOVE);
}
}
break;
case GS_COMPUTER_MOVE:
// Check for opening move or calculate next move
bx = board_opening(TheGame.step, TheGame.moves);
if (bx == 0xff)
bx = board_check(0, -32767, 32767, false);
// Drop piece into board
if (board_drop(bx, false))
{
// Play drop animation
item_drop_anim(&cwm, bx, board.ffree[bx], 2);
// Show new state of the board
board_draw_main(&cwm);
spr_show(0, false);
// Check for loss or draw condition
if (board_eval(false) == 32000)
game_state(GS_COMPUTER_WIN);
else if (TheGame.step == 21)
game_state(GS_GAME_OVER);
else
game_state(GS_PLAYER_MOVE);
}
break;
case GS_PLAYER_WIN:
case GS_COMPUTER_WIN:
case GS_GAME_OVER:
if (!--TheGame.count)
game_state(GS_READY);
break;
}
}
int main(void)
{
mmap_trampoline();
// Install character set
mmap_set(MMAP_RAM);
memcpy(Font, charset, 2048);
memcpy(Sprites, spriteset, 256);
mmap_set(MMAP_NO_BASIC);
// Switch screen
vic_setmode(VICM_TEXT_MC, Screen, Font);
spr_init(Screen);
// Change colors
vic.color_border = VCOL_BLUE;
vic.color_back = VCOL_BLACK;
vic.color_back1 = VCOL_BLUE;
vic.color_back2 = VCOL_WHITE;
vic.spr_mcolor0 = VCOL_DARK_GREY;
vic.spr_mcolor1 = VCOL_WHITE;
// Clear screen
memset(Screen, 96, 1000);
memset(Color, 15, 1000);
// Prepare char wins
cwin_init(&cws, Screen, 5, 0, 30, 1);
cwin_init(&cwm, Screen, 2, 3, 28, 19);
cwin_init(&cw, Screen, 30, 6, 8, 7);
cwin_init(&cwt, Screen, 30, 15, 8, 7);
// Init AI
ai_init();
game_state(GS_READY);
for(;;)
{
game_loop();
vic_waitFrame();
}
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

+279
View File
@@ -0,0 +1,279 @@
#include <c64/joystick.h>
#include <c64/vic.h>
#include <c64/sprites.h>
#include <stdlib.h>
#include <string.h>
byte landersprites[] = {
#embed "../resources/landersprites.bin"
};
// Screen and color ram address
#define Screen ((byte *)0x0400)
#define Color ((byte *)0xd800)
struct Lander
{
float px, py, vx, vy;
};
enum GameState
{
GS_READY, // Getting ready
GS_PLAYING, // Playing the game
GS_LANDED, // Landed on pad
GS_COLLIDE // Collided with something
};
// State of the game
struct Game
{
GameState state;
byte count;
Lander lander; // use an array for multiplayer
} TheGame; // Only one game, so global variable
// Put one char on screen
inline void screen_put(byte x, byte y, char ch, char color)
{
__assume(y < 25);
Screen[40 * y + x] = ch;
Color[40 * y + x] = color;
}
// Get one char from screen
inline char screen_get(byte x, byte y)
{
__assume(y < 25);
return Screen[40 * y + x];
}
void screen_init(void)
{
// Fill screen with spaces
memset(Screen, ' ', 1000);
for(char i=0; i<100; i++)
screen_put(rand() % 40, rand() % 25, '.', VCOL_WHITE);
sbyte height[41];
for(char i=0; i<41; i+=8)
height[i] = 4 + rand() % 16;
for(char step = 8; step > 1; step /= 2)
{
for(char i=0; i<40; i+=step)
{
char p = (height[i] + height[i + step]) >> 1;
p += rand() % step - (step / 2);
height[i + step / 2] = p;
}
}
char xp = 2 + rand() % 33;
char yp = height[xp];
for(char i=1; i<4; i++)
if (height[xp + i] < yp)
yp = height[xp + i];
for(char i=0; i<4; i++)
height[xp + i] = yp;
for(char x=0; x<40; x++)
{
char h = height[x];
for(char y=0; y<h; y++)
screen_put(x, 24 - y, 160, VCOL_YELLOW);
}
for(char i=0; i<4; i++)
{
screen_put(xp + i, 24 - yp, 128 + 86, VCOL_MED_GREY);
screen_put(xp + i, 23 - yp, 100, VCOL_WHITE);
}
}
void lander_init(Lander * lander)
{
lander->px = 160;
lander->py = 50;
lander->vx = 0;
lander->vy = 0;
spr_set(0, true, (int)lander->px, (int)lander->py, 0x0380 / 64, VCOL_DARK_GREY, false, false, false);
spr_set(1, true, (int)lander->px, (int)lander->py, 0x0340 / 64, VCOL_LT_GREY, true, false, false);
spr_set(2, false, (int)lander->px, (int)lander->py + 20, 0x03c0 / 64, VCOL_WHITE, false, false, false);
}
char ExhaustColor[] = {VCOL_YELLOW, VCOL_WHITE, VCOL_ORANGE, VCOL_LT_BLUE};
void lander_move(Lander * lander, sbyte jx, sbyte jy)
{
lander->px += lander->vx;
lander->py += lander->vy;
lander->vx += jx * 0.02;
lander->vy += jy * 0.1 + 0.01;
}
void lander_show(Lander * lander, sbyte jx, sbyte jy)
{
vic.color_border++;
int ix = (int)lander->px, iy = (int)lander->py;
spr_move(0, ix, iy);
spr_move(1, ix, iy);
if (jy < 0)
{
spr_move(2, ix, iy + 20);
spr_color(2, ExhaustColor[rand() & 3]);
spr_show(2, true);
}
else
spr_show(2, false);
vic.color_border--;
}
void lander_flash(Lander * lander, char c)
{
spr_color(0, rand() & 1);
}
enum LanderCollision
{
LCOL_FREE,
LCOL_GROUND,
LCOL_PAD
};
LanderCollision lander_check(Lander * lander)
{
sbyte ix = (sbyte)((lander->px - 24) * 0.125);
sbyte iy = (sbyte)((lander->py - 29) * 0.125);
if (iy > 24)
return LCOL_GROUND;
if (iy < 0)
return LCOL_FREE;
LanderCollision col = LCOL_FREE;
for(char i=0; i<4; i++)
{
if (ix >= 0 && ix < 40)
{
char ch = screen_get(ix, iy);
if (ch == 160)
return LCOL_GROUND;
else if (ch == 128 + 86)
col = LCOL_PAD;
}
ix++;
}
return col;
}
void game_state(GameState state)
{
// Set new state
TheGame.state = state;
switch(state)
{
case GS_READY:
// Clear the screen
lander_init(&TheGame.lander);
screen_init();
TheGame.count = 32;
break;
case GS_PLAYING:
break;
case GS_LANDED:
TheGame.lander.py = (sbyte)((TheGame.lander.py - 29) * 0.125) * 8 + 28;
lander_show(&TheGame.lander, 0, 0);
TheGame.count = 16;
break;
case GS_COLLIDE:
TheGame.count = 32;
lander_show(&TheGame.lander, 0, 0);
break;
}
}
// Main game loop, invoked every vsync
void game_loop(void)
{
switch (TheGame.state)
{
case GS_READY:
// Countdown ready to start
if (!--TheGame.count)
game_state(GS_PLAYING);
break;
case GS_PLAYING:
{
// Check player input on every frame
joy_poll(0);
lander_move(&TheGame.lander, joyx[0], joyy[0]);
LanderCollision col = lander_check(&TheGame.lander);
if (col == LCOL_GROUND)
game_state(GS_COLLIDE);
else if (col == LCOL_PAD)
game_state(GS_LANDED);
else
lander_show(&TheGame.lander, joyx[0], joyy[0]);
} break;
case GS_LANDED:
if (!--TheGame.count)
game_state(GS_READY);
break;
case GS_COLLIDE:
lander_flash(&TheGame.lander, TheGame.count);
if (!--TheGame.count)
game_state(GS_READY);
break;
}
}
int main(void)
{
// Screen color to black
vic.color_border = VCOL_BLACK;
vic.color_back = VCOL_BLACK;
vic.spr_mcolor0 = VCOL_MED_GREY;
vic.spr_mcolor1 = VCOL_YELLOW;
memcpy((char *)0x0340, landersprites, 192);
spr_init(Screen);
// Start the game in ready state
game_state(GS_READY);
// Forever
for(;;)
{
// One game loop iteration
game_loop();
// Wait one vsync
vic_waitFrame();
}
// Never reached
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

+7
View File
@@ -0,0 +1,7 @@
call ..\..\bin\oscar64 snake.c
call ..\..\bin\oscar64 -n lander.c
call ..\..\bin\oscar64 -n maze3d.c
call ..\..\bin\oscar64 -n -O3 missile.c
call ..\..\bin\oscar64 -n breakout.c
call ..\..\bin\oscar64 -n connectfour.c
call ..\..\bin\oscar64 -n -O2 hscrollshmup.c
+17
View File
@@ -0,0 +1,17 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: snake.prg lander.prg maze3d.prg missile.prg breakout.prg connectfour.prg hscrollshmup.prg
snake.prg: snake.c
@$(OSCAR64_CC) $<
missile.prg: missile.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) -O3 $<
hscrollshmup.prg: hscrollshmup.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) -O2 $<
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg *.bcs
+485
View File
@@ -0,0 +1,485 @@
#include <c64/joystick.h>
#include <c64/vic.h>
#include <c64/sprites.h>
#include <c64/memmap.h>
#include <c64/rasterirq.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
// Moving the VIC into the third bank and making
// room for double buffering+
byte * const Screen0 = (byte *)0xc800;
byte * const Screen1 = (byte *)0xcc00;
byte * const Font = (byte *)0xd000;
byte * const Color = (byte *)0xd800;
byte * const Color1 = (byte *)0xc400;
// Just to get started a mini maze
static const char * maze[16] =
{
"################",
"#..........#...#",
"#.###.####.###.#",
"#........#.#.#.#",
"##.#####.###.#.#",
"#..#......##.#.#",
"#.##.####......#",
"#.#.....#.####.#",
"#.#####.#....#.#",
"#.......######.#",
"#.##.####......#",
"#.#..##...####.#",
"#.##....#....#.#",
"#.#####.######.#",
"#..............#",
"################",
};
// Character set including some ramps for the upper edge
char charset[2048] = {
#embed "../resources/maze3dchars.bin"
};
// Current target screen
char * DrawScreen;
// Current target index
bool FlipIndex;
// Position and direction inside the maze
sbyte px = 1, py = 3, dx = 1, dy = 0;
// Distance of blocks to the side, relative to the center of the screen
// for full and half step
static const char zxdist0[] = {18, 6, 4, 3, 2, 1, 0};
static const char zxdist1[] = { 9, 5, 3, 2, 1, 0, 0};
// Flip double buffer, copying the color ram
void screen_flip(void)
{
// Change idnex of screen
FlipIndex = !FlipIndex;
// Wait until raster beam reaches bottom
vic_waitBottom();
// Change vic start address
vic_setmode(VICM_TEXT, FlipIndex ? Screen0 : Screen1, Font);
// Copy the color ram in four chunks, to avoid
// colliding with the beam
char i = 0;
do {
Color[0x000 + i] = Color1[0x000 + i];
i++;
} while (i != 0);
do {
Color[0x100 + i] = Color1[0x100 + i];
i++;
} while (i != 0);
do {
Color[0x200 + i] = Color1[0x200 + i];
i++;
} while (i != 0);
do {
Color[0x300 + i] = Color1[0x300 + i];
i++;
} while (i != 0);
// Change target buffer for next frame
DrawScreen = FlipIndex ? Screen1 : Screen0;
}
// Rotating left or right is simulated by scrolling. For
// performance reasons, we have four different scroll routines
// due to two buffers and two directions
// Loop over the two buffers
#assign si 0
#repeat
// other buffer
#assign ri 1 - si
// pointers of the two screen buffers, from and to
#define dst Screen##si
#define src Screen##ri
// scroll left Screen0 or Screen1
void screen_left_##si(void)
{
for(char sx=0; sx<40; sx+=4)
{
// Wait for the beam to be just below the first line
vic_waitLine(58);
// Unroll for each row of screen and color ram
#assign ry 0
#repeat
// Copy one row by four chars
for(char x=0; x<36; x++)
{
dst[40 * ry + x] = dst[40 * ry + x + 4];
Color[40 * ry + x] = Color[40 * ry + x + 4];
}
// Fill in new screen and color data
dst[40 * ry + 36] = src[40 * ry + sx + 0];
dst[40 * ry + 37] = src[40 * ry + sx + 1];
dst[40 * ry + 38] = src[40 * ry + sx + 2];
dst[40 * ry + 39] = src[40 * ry + sx + 3];
Color[40 * ry + 36] = Color1[40 * ry + sx + 0];
Color[40 * ry + 37] = Color1[40 * ry + sx + 1];
Color[40 * ry + 38] = Color1[40 * ry + sx + 2];
Color[40 * ry + 39] = Color1[40 * ry + sx + 3];
// repeat for each row
#assign ry ry + 1
#until ry == 25
#undef ry
}
}
// scroll right Screen0 or Screen1
void screen_right_##si(void)
{
for(char sx=40; sx>0; sx-=4)
{
vic_waitLine(58);
#assign ry 0
#repeat
for(char x=39; x>=4; x--)
{
dst[40 * ry + x] = dst[40 * ry - 4 + x];
Color[40 * ry + x] = Color[40 * ry - 4 + x];
}
dst[40 * ry + 0] = src[40 * ry + sx - 4];
dst[40 * ry + 1] = src[40 * ry + sx - 3];
dst[40 * ry + 2] = src[40 * ry + sx - 2];
dst[40 * ry + 3] = src[40 * ry + sx - 1];
Color[40 * ry + 0] = Color1[40 * ry + sx - 4];
Color[40 * ry + 1] = Color1[40 * ry + sx - 3];
Color[40 * ry + 2] = Color1[40 * ry + sx - 2];
Color[40 * ry + 3] = Color1[40 * ry + sx - 1];
#assign ry ry + 1
#until ry == 25
#undef ry
}
}
#assign si si + 1
#until si == 2
#undef si
#undef ri
// Scroll current screen left
void screen_left(void)
{
if (FlipIndex)
screen_left_0();
else
screen_left_1();
}
// Scroll current screen right
void screen_right(void)
{
if (FlipIndex)
screen_right_0();
else
screen_right_1();
}
// Fill one color column
void color_column(char cx, char color)
{
#assign ry 0
#repeat
Color1[40 * ry + cx] = color;
#assign ry ry + 1
#until ry == 25
#undef ry
}
// Fill one screen column
void screen_column(char cx, char sx, char tc, char mc, char bc)
{
// Calculate top and bottom row
char ty = sx / 4;
char by = 25 - sx;
// Target pointer
char * dp = DrawScreen + cx;
// Check for non empty column
if (by > ty)
{
// Space above
for(char cy=0; cy<ty; cy++)
{
*dp = 126; dp += 40;
}
// Top element
*dp = tc; dp += 40;
// Wall body
char n = by - ty - 2;
for(char cy=0; cy<n; cy++)
{
*dp = mc; dp += 40;
}
// Bottom element
*dp = bc; dp += 40;
// Space below
for(char cy=by; cy<25; cy++)
{
*dp = 126; dp += 40;
}
}
else
{
// Special case, clear column
for(char cy=0; cy<25; cy++)
{
*dp = 126; dp += 40;
}
}
}
// Draw the current maze using the given z/x distance array
void maze_draw(const char * zxdist)
{
// pick colors based on orientation
char cleft, cright, cfront;
if (dx)
{
cfront = VCOL_MED_GREY;
if (dx < 0)
{
cleft = VCOL_LT_GREY;
cright = VCOL_DARK_GREY;
}
else
{
cleft = VCOL_DARK_GREY;
cright = VCOL_LT_GREY;
}
}
else
{
cleft = cright = VCOL_MED_GREY;
cfront = dy > 0 ? VCOL_LT_GREY : VCOL_DARK_GREY;
}
// Start position of player
sbyte ix = px, iy = py;
// Starting at first screen column
sbyte sx = 0;
for(char i=0; i<7; i++)
{
// Next screen column
sbyte tx = 20 - zxdist[i];
// View blocked by wall
if (maze[iy][ix] == '#')
{
// Fill with wall color
for(char cx=sx; cx<40-sx; cx++)
{
color_column(cx, cfront);
screen_column(cx, sx, 96 + (sx & 3), 96, 96);
}
// And be done
return ;
}
// Check for left wall
if (maze[iy - dx][ix + dy] == '#')
{
// Draw left wall
for(char cx=sx; cx<tx; cx++)
{
// Perspective
sbyte ty = cx / 4;
sbyte by = 25 - cx;
color_column(cx, cleft);
screen_column(cx, cx, 100 + (cx & 3), 96, 124);
}
}
else
{
// Draw adjacent wall visible due to free space left
sbyte ty = tx / 4;
sbyte by = 25 - tx;
// All at same height, wall is facing us
for(char cx=sx; cx<tx; cx++)
{
color_column(cx, cfront);
screen_column(cx, tx, 96 + (tx & 3), 96, 96);
}
}
// Check for right wall
if (maze[iy + dx][ix - dy] == '#')
{
for(char cx=sx; cx<tx; cx++)
{
sbyte ty = cx / 4;
sbyte by = 25 - cx;
color_column(39 - cx, cright);
screen_column(39 - cx, cx, 107 - (cx & 3), 96, 125);
}
}
else
{
sbyte ty = tx / 4;
sbyte by = 25 - tx;
for(char cx=sx; cx<tx; cx++)
{
color_column(39 - cx, cfront);
screen_column(39 - cx, tx, 96 + (tx & 3), 96, 96);
}
}
// Advance in maze
sx = tx;
ix += dx;
iy += dy;
}
}
// Raster interrupts for ceiling and floor colors
RIRQCode center, bottom;
int main(void)
{
mmap_trampoline();
// Install character set
mmap_set(MMAP_RAM);
memcpy(Font, charset, 2048);
mmap_set(MMAP_NO_BASIC);
// Switch screen
vic_setmode(VICM_TEXT, Screen0, Font);
// Change colors
vic.color_border = VCOL_BLACK;
// initialize raster IRQ
rirq_init(true);
// Build switch to scroll line IRQ
rirq_build(&center, 1);
// Change color for floor
rirq_write(&center, 0, &vic.color_back, VCOL_BLACK);
// Put it into the perspective focus point
rirq_set(0, 50 + 2 * 20, &center);
// Build the switch to normal IRQ
rirq_build(&bottom, 1);
// Change color for ceiling
rirq_write(&bottom, 0, &vic.color_back, VCOL_WHITE);
// place this at the bottom
rirq_set(1, 250, &bottom);
// sort the raster IRQs
rirq_sort();
// start raster IRQ processing
rirq_start();
// Block multiple rotations
bool rotate = false;
// Draw initial frame
screen_flip();
maze_draw(zxdist0);
screen_flip();
for(;;)
{
// Read joystick input
joy_poll(0);
// Forward or backward motion
if (joyy[0])
{
// Target square
sbyte tx = px - dx * joyy[0];
sbyte ty = py - dy * joyy[0];
// Check i empty
if (maze[ty][tx] != '#')
{
if (joyy[0] < 0)
{
// Forward animation
px = tx;
py = ty;
maze_draw(zxdist1);
screen_flip();
}
else
{
// Backward animation
maze_draw(zxdist1);
screen_flip();
px = tx;
py = ty;
}
}
// New frame at new position
maze_draw(zxdist0);
screen_flip();
}
// Check if new rotation
if (!rotate)
{
if (joyx[0] == 1)
{
// Rotate right
sbyte t = dx; dx = -dy; dy = t;
rotate = true;
maze_draw(zxdist0);
screen_left();
}
else if (joyx[0] == -1)
{
// Rotate left
sbyte t = dx; dx = dy; dy = -t;
rotate = true;
maze_draw(zxdist0);
screen_right();
}
}
else if (!joyx[0])
{
// No rotation, may rotate again in next frame
rotate = false;
}
}
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+869
View File
@@ -0,0 +1,869 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <c64/sprites.h>
#include <c64/joystick.h>
#include <c64/rasterirq.h>
#include <c64/cia.h>
#include <gfx/mcbitmap.h>
#include <string.h>
#include <stdlib.h>
// Make some room
#pragma region(main, 0x0a00, 0xc800, , , {code, data, bss, heap, stack} )
// Sprite assets
const char MissileSprites[] = {
#embed "../resources/missilesprites.bin"
};
// Charset assets
const char MissileChars[] = {
#embed "../resources/missilechars.bin"
};
// Graphics areas in bank 3
#define Color1 ((char *)0xc800)
#define Color2 ((char *)0xd800)
#define Hires ((char *)0xe000)
#define Sprites ((char *)0xd000)
#define Charset ((char *)0xd800)
// Joystick and crosshair control
volatile int CrossX = 160, CrossY = 100;
bool CrossP = false;
char CrossDelay = 0;
// Display bitmap
Bitmap sbm;
const ClipRect scr = { 0, 0, 320, 200 };
// Structure for a explosion
struct Explosion
{
int x, y; // Center of circle
char r; // Radius of circle
Explosion * next; // Next explosion in list
};
// Structure for a missile (defensive and ICBM)
struct Missile
{
int sx, sy; // start position
int tx, ty; // target position
int x, y; // current position
int dx, dy; // distance in x and y
int d; // error term for Bresenham
sbyte stepx; // direction in x (+1 or -1)
sbyte cnt; // speed counter
Missile * next; // next missile in list
};
// Storage space for explosion
Explosion explosions[16];
// First free and first used explosion
Explosion * efree, * eused;
// Storage space for defending missiles
Missile missiles[8];
// First free and first used missile
Missile * mfree, * mused;
// Number of missiles available
char nmissiles;
// Storage space for ICMBs
Missile icbms[16];
// First free and first used ICBM
Missile * ifree, * iused;
// Speed and number of ICBMs still incoming
char icbmspeed, icbmcount;
// Cities not yet destroyed
bool cities[6];
char ncities;
// Init status bar at top
void status_init(void)
{
memset(Color1, ' ', 40);
memset(Color2, 1, 40);
for(char i=0; i<8; i++)
{
Color1[i + 2] = '0';
Color1[i + 12] = '0';
Color2[i + 12] = 7;
}
}
// Expand an 8x8 character to 16x16 on screen
void char_put(char cx, char cy, char c, char color)
{
// Get pointer to glyph data
const char * sp = MissileChars + 8 * c;
// Loop over all pixel
for(char y=0; y<8; y++)
{
char cl = sp[y];
for(char x=0; x<8; x++)
{
// Draw two pixel if bit is set
if (cl & 128)
{
bmmc_put(&sbm, cx + 2 * x, cy + 2 * y + 0, color);
bmmc_put(&sbm, cx + 2 * x, cy + 2 * y + 1, color);
}
// Next bit
cl <<= 1;
}
}
}
// Write a zero terminated string on screen
void char_write(char cx, char cy, const char * s, char color)
{
// Loop over all characters
while (*s)
{
char_put(cx, cy, *s, color);
s++;
cx += 16;
}
}
// Increment the score from a given digit on
void score_inc(char digit, unsigned val)
{
// Lowest digit to increment
char at = 9 - digit;
// Loop while there is still score to account for
while (val)
{
// Increment one character
char ch = Color1[at] + val % 10;
// Remove low digit from number
val /= 10;
// Check overflow
if (ch > '9')
{
ch -= 10;
val++;
}
Color1[at] = ch;
// Next higher character
at --;
}
}
// Reset score and update high score
void score_reset(void)
{
// Find first digit, where score and highscore differ
char i = 0;
while (i < 8 && Color1[i + 2] == Color1[i + 12])
i++;
// Check if new score is higher
if (i < 8 && Color1[i + 2] > Color1[i + 12])
{
// If so, copy to highscore
while (i < 8)
{
Color1[i + 12] = Color1[i + 2];
i++;
}
}
// Clear score
for(char i=0; i<8; i++)
Color1[i + 2] = '0';
}
// Update number of missiles
void status_missiles(char num)
{
char n = 0;
// Draw full pairs
while (2 * n + 1 < num)
{
Color1[25 + n] = 92;
n++;
}
// Draw remaining single one
if (num & 1)
{
Color1[25 + n] = 93;
n++;
}
// Empty remainder
while (n < 15)
{
Color1[25 + n] = 94;
n++;
}
}
// Initialize explosion list
void explosion_init(void)
{
// No explosion active
eused = nullptr;
// First free explosion element
efree = explosions;
// Build list
for(char i=0; i<15; i++)
explosions[i].next = explosions + i + 1;
// Terminate last element
explosions[15].next = nullptr;
}
// Start a new explosion
void explosion_start(int x, int y)
{
// Free slot in list of explosions?
if (efree)
{
// Move entry from free to used list
Explosion * e = efree;
efree = e->next;
e->next = eused;
eused = e;
// Initialize position and size
e->r = 0;
e->x = x;
e->y = y;
}
}
// Animate all explosions
void explosion_animate(void)
{
// Loop over active explosions with "e", use "ep" to point
// to previous explosion, so we can remove the current explosion
// from the list
Explosion * e = eused, * ep = nullptr;
while (e)
{
// Remember next entry in list
Explosion * en = e->next;
// Increment phase (radius)
e->r++;
// Advance every fourth frame
if (!(e->r & 3))
{
// Draw or erase outer perimeter depending on growing or
// shrinking explosion phase
if (e->r <= 64)
bmmc_circle(&sbm, &scr, e->x, e->y, e->r >> 2, 1);
else
bmmc_circle(&sbm, &scr, e->x, e->y, 33 - (e->r >> 2), 0);
}
// End of explosion live
if (e->r == 128)
{
// Remove explosion from used list
if (ep)
ep->next = e->next;
else
eused = e->next;
// Prepend it to free list
e->next = efree;
efree = e;
}
else
ep = e;
// Next explosion in list
e = en;
}
}
// Initialize defending missile list
void missile_init(void)
{
mused = nullptr;
mfree = missiles;
for(char i=0; i<7; i++)
missiles[i].next = missiles + i + 1;
missiles[7].next = nullptr;
}
// Add a new defending missile
void missile_start(int sx, int sy, int tx, int ty)
{
// Check if entry in free list and missile in silo remaining
if (mfree && nmissiles > 0)
{
// Detach from free list
Missile * m = mfree;
mfree = m->next;
// Attach to active list
m->next = mused;
mused = m;
// Initialize start and target coordinates
m->sx = sx >> 1; m->x = sx >> 1;
m->sy = sy; m->y = sy;
m->tx = tx >> 1;
m->ty = ty;
// Initialize line drawing parameters
m->dy = m->sy - m->ty;
m->dx = m->tx - m->sx;
m->stepx = 1;
if (m->dx < 0)
{
m->dx = -m->dx;
m->stepx = -1;
}
m->d = m->dy - m->dx;
m->dx *= 2;
m->dy *= 2;
// Remove missile from silo
nmissiles--;
status_missiles(nmissiles);
}
}
// Animate all active missiles
void missile_animate(void)
{
Missile * m = mused, * mp = nullptr;
while (m)
{
Missile * mn = m->next;
// Advance missile position using one step of Bresenham
if (m->d >= 0)
{
m->y--;
m->d -= m->dx;
}
if (m->d < 0)
{
m->x += m->stepx;
m->d += m->dy;
}
// Check if target reached
if (m->y == m->ty)
{
// If so, clear line and start explosion
bmmcu_line(&sbm, m->sx * 2, m->sy, m->tx * 2, m->ty, 0);
explosion_start(m->x * 2, m->y);
// Remove from active list
if (mp)
mp->next = m->next;
else
mused = m->next;
m->next = mfree;
mfree = m;
}
else
{
// Draw new pixel in missile trace
bmmc_put(&sbm, m->x * 2, m->y, 3);
mp = m;
}
m = mn;
}
}
// Initialize incoming ICBM list
void icbm_init(void)
{
iused = nullptr;
ifree = icbms;
for(char i=0; i<15; i++)
icbms[i].next = icbms + i + 1;
icbms[15].next = nullptr;
}
// Add a new ICBM to the attacking set
void icbm_start(int sx, int sy, int tx, int ty)
{
if (icbmcount && ifree)
{
Missile * m = ifree;
ifree = m->next;
m->next = iused;
iused = m;
m->sx = sx >> 1; m->x = sx >> 1;
m->sy = sy; m->y = sy;
m->tx = tx >> 1;
m->ty = ty;
m->cnt = 0;
m->dy = m->ty - m->sy;
m->dx = m->tx - m->sx;
m->stepx = 1;
if (m->dx < 0)
{
m->dx = -m->dx;
m->stepx = -1;
}
m->d = m->dy - m->dx;
m->dx *= 2;
m->dy *= 2;
icbmcount--;
}
}
void icbm_animate(void)
{
Missile * m = iused, * mp = nullptr;
while (m)
{
Missile * mn = m->next;
// Check speed of ICBMs
m->cnt += icbmspeed;
while (m->cnt > 0)
{
m->cnt -= 32;
// Draw pixel in trace
bmmc_put(&sbm, m->x * 2, m->y, 2);
// Advance using Bresenham
if (m->d >= 0)
{
m->y++;
m->d -= m->dx;
}
if (m->d < 0)
{
m->x += m->stepx;
m->d += m->dy;
}
// Check if colliding with cloud or target reached
if (bmmc_get(&sbm, m->x * 2, m->y) == 1 || m->y == m->ty)
{
// If so, clear trace and start explosion
bmmcu_line(&sbm, m->sx * 2, m->sy, m->tx * 2, m->ty, 0);
explosion_start(m->x * 2, m->y);
// Check if we hit the ground
if (m->y == m->ty)
{
// If so, find matching city
int x = m->x * 2;
char ix;
if (x > 160)
ix = ((x - 202) >> 5) + 3;
else
ix = (x - 58) >> 5;
// Destroy, destroy, annihilate, kill, kill
if (cities[ix])
{
ncities--;
cities[ix] = false;
spr_show(ix + 1, false);
}
}
// Add score for destroyed ICBM
score_inc(0, 25);
// Remove from list
if (mp)
mp->next = m->next;
else
iused = m->next;
m->next = ifree;
ifree = m;
m = nullptr;
// End loop early
break;
}
}
// If ICBM still in flight
if (m)
{
// Remember for list management
mp = m;
// Draw white head
bmmc_put(&sbm, m->x * 2, m->y, 1);
}
m = mn;
}
}
// Initialize game screen
void screen_init(void)
{
// Clean up
bmmcu_rect_fill(&sbm, 0, 8, 320, 184, 0);
// Draw bottom
bmmcu_rect_fill(&sbm, 0, 192, 320, 8, 3);
bmmc_quad_fill(&sbm, &scr, 0, 192, 16, 184, 32, 184, 48, 192, MixedColors[3][3]);
bmmc_quad_fill(&sbm, &scr, 136, 192, 152, 184, 176, 184, 192, 192, MixedColors[3][3]);
bmmc_quad_fill(&sbm, &scr, 272, 192, 288, 184, 304, 184, 320, 192, MixedColors[3][3]);
// Show cities
for(char i=0; i<3; i++)
{
if (cities[i + 0])
spr_set(i + 1, true, 70 + 32 * i, 222, 65, 15, false, false, false);
if (cities[i + 3])
spr_set(i + 4, true, 214 + 32 * i, 222, 65, 15, false, false, false);
}
}
// Clear inner area of screen
void screen_clear(void)
{
bmmcu_rect_fill(&sbm, 0, 8, 320, 176, 0);
}
// Interrupt routine for joystick control, called by raster IRQ at bottom
// of screen
__interrupt void joy_interrupt()
{
// vic.color_border++;
// Poll joystick
joy_poll(0);
// Move crosshair coordinates
int cx = CrossX + 2 * joyx[0], cy = CrossY + 2 * joyy[0];
// Stop at edges of screen
if (cx < 8)
cx = 8;
else if (cx > 312)
cx = 312;
if (cy < 20)
cy = 20;
else if (cy > 172)
cy = 172;
// Move crosshair sprite
spr_move(0, cx + 14, cy + 40);
CrossX = cx;
CrossY = cy;
// Check button
if (joyb[0])
{
// Avoid quickfire and bouncing
if (CrossDelay == 0)
{
// Request fire from non interrupt code
CrossP = true;
CrossDelay = 4;
}
}
else if (CrossDelay > 0)
CrossDelay--;
// vic.color_border--;
}
enum GameState
{
GS_READY, // Getting ready
GS_LEVEL, // Show level message
GS_PLAYING, // Playing the game
GS_BONUS, // Landed on pad
GS_ARMAGEDDON, // Show end game animation
GS_END // Wait for restart
};
// State of the game
struct Game
{
GameState state;
byte count, level;
} TheGame; // Only one game, so global variable
// Character buffer for some texts
char cbuffer[10];
void game_state(GameState state)
{
TheGame.state = state;
switch(state)
{
case GS_READY:
// Start of new game
score_reset();
screen_init();
char_write(40, 100, s"READY PLAYER 1", 3);
// New cities
for(char i=0; i<6; i++)
cities[i] = true;
ncities = 6;
TheGame.count = 60;
// Starting at level 1
TheGame.level = 0;
break;
case GS_LEVEL:
// Advance to next level
TheGame.level++;
utoa(TheGame.level ,cbuffer, 10);
screen_clear();
char_write(96, 100, s"LEVEL", 3);
char_write(96 + 16 * 6, 100, cbuffer, 3);
TheGame.count = 30;
break;
case GS_PLAYING:
// Avoid old fire request
CrossP = false;
// Setup display
screen_init();
missile_init();
explosion_init();
icbm_init();
// A new set of 30 missiles
nmissiles = 30;
status_missiles(nmissiles);
// Game parameters based on level
if (TheGame.level < 112)
icbmspeed = 8 + TheGame.level;
else
icbmspeed = 120;
if (TheGame.level < 50)
icbmcount = 5 + TheGame.level / 2;
else
icbmcount = 30;
TheGame.count = 15;
break;
case GS_BONUS:
{
// Show bonus
unsigned bonus = ncities * 50 + nmissiles * 5;
utoa(bonus, cbuffer, 10);
char_write(96, 100, s"BONUS", 3);
char_write(96 + 16 * 6, 100, cbuffer, 3);
score_inc(0, bonus);
TheGame.count = 30;
} break;
case GS_ARMAGEDDON:
TheGame.count = 0;
break;
case GS_END:
char_write(104, 92, s"THE END", 0);
TheGame.count = 120;
break;
}
}
// Main game play code
void game_play(void)
{
// Check if fire request
if (CrossP)
{
int cx = CrossX, cy = CrossY;
// Find launch site
int sx = 160;
if (cx < 120)
sx = 24;
else if (cx > 200)
sx = 296;
// Fire missile
missile_start(sx, 184, cx, cy);
// Reset request
CrossP = false;
}
// Wait for next ICMB to enter the game
if (!--TheGame.count)
{
// Pick target city
char ci;
do {
ci = rand() & 7;
} while (ci >= 6 || !cities[ci]);
int cx;
if (ci < 3)
cx = 58 + 32 * ci;
else
cx = 202 + 32 * (ci - 3);
// Launch ICBM
icbm_start((rand() & 0xff) + 32, 0, cx, 184);
// Next launch time
TheGame.count = 8 + (rand() & 63);
}
// Advance defending missiles by four pixels
for(char i=0; i<4; i++)
missile_animate();
// Advance ICBMs
icbm_animate();
// Show explosions
explosion_animate();
}
// Main game loop, entered every VSYNC, slower if too busy with explosions
void game_loop(void)
{
switch(TheGame.state)
{
case GS_READY:
if (!--TheGame.count)
game_state(GS_LEVEL);
break;
case GS_LEVEL:
if (!--TheGame.count)
game_state(GS_PLAYING);
break;
case GS_PLAYING:
game_play();
// Check for level and game end conditions
if (!icbmcount && !iused && !eused)
game_state(GS_BONUS);
else if (ncities == 0)
game_state(GS_ARMAGEDDON);
break;
case GS_BONUS:
if (!--TheGame.count)
game_state(GS_LEVEL);
break;
case GS_ARMAGEDDON:
// Draw end game animation
TheGame.count++;
bmmc_circle(&sbm, &scr, 160, 100, TheGame.count, 1);
explosion_animate();
if (TheGame.count == 90)
game_state(GS_END);
break;
case GS_END:
if (!--TheGame.count)
game_state(GS_READY);
break;
}
}
// Interrupts for status line and joystick routine
RIRQCode bottom, top;
int main(void)
{
// Activate trampoline
mmap_trampoline();
// Disable CIA interrupts, we do not want interference
// with our joystick interrupt
cia_init();
// Copy assets
mmap_set(MMAP_RAM);
memcpy(Sprites, MissileSprites, 1024);
memcpy(Charset, MissileChars, 2048);
mmap_set(MMAP_NO_ROM);
// Clean out screen space
memset(Color1, 0x18, 1000);
memset(Color2, 0x06, 1000);
memset(Hires, 0, 8000);
memset(Color2 + 40 * 23, 0x07, 80);
// initialize raster IRQ
rirq_init(true);
// Switch to hires mode
vic_setmode(VICM_HIRES_MC, Color1, Hires);
spr_init(Color1);
// Black background and border
vic.color_back = VCOL_BLACK;
vic.color_border = VCOL_BLACK;
// Init bitmap
bm_init(&sbm, Hires, 40, 25);
// Init status line
status_init();
// Init cross hair sprite
spr_set(0, true, CrossX + 14, CrossY + 40, 64, 1, false, false, false);
// Build to multicolor highres at top of screen
rirq_build(&top, 3);
rirq_delay(&top, 10);
rirq_write(&top, 1, &vic.ctrl1, VIC_CTRL1_BMM | VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
rirq_write(&top, 2, &vic.memptr, 0x28);
rirq_set(0, 57, &top);
// Switch to text mode for status line and poll joystick at bottom
rirq_build(&bottom, 3);
rirq_write(&bottom, 0, &vic.memptr, 0x27);
rirq_write(&bottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
rirq_call(&bottom, 2, joy_interrupt);
rirq_set(1, 252, &bottom);
// sort the raster IRQs
rirq_sort();
// start raster IRQ processing
rirq_start();
// start game state machine
game_state(GS_READY);
for(;;)
{
game_loop();
rirq_wait();
}
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

+282
View File
@@ -0,0 +1,282 @@
#include <c64/joystick.h>
#include <c64/vic.h>
#include <stdlib.h>
#include <string.h>
// Position/Direction on screen
struct Point
{
sbyte x, y;
};
struct Snake
{
Point head; // Position of head
Point dir; // Direction of head
Point tail[256]; // Position of tail
byte length; // Length of tail
byte pos; // Tail start
};
enum GameState
{
GS_READY, // Getting ready
GS_PLAYING, // Playing the game
GS_COLLIDE // Collided with something
};
// State of the game
struct Game
{
GameState state;
byte count;
Snake snake; // use an array for multiplayer
} TheGame; // Only one game, so global variable
// Screen and color ram address
#define Screen ((byte *)0x0400)
#define Color ((byte *)0xd800)
// Put one char on screen
inline void screen_put(byte x, byte y, char ch, char color)
{
Screen[40 * y + x] = ch;
Color[40 * y + x] = color;
}
// Get one char from screen
inline char screen_get(byte x, byte y)
{
return Screen[40 * y + x];
}
// Put a fruit/heart at random position
void screen_fruit(void)
{
byte x, y;
do
{
// Draw a random position
x = 1 + rand() % 38;
y = 1 + rand() % 23;
// Ensure it is an empty place
} while (screen_get(x, y) != ' ');
// Put the heart on screen
screen_put(x, y, 83, VCOL_YELLOW);
}
// Clear screen and draw borders
void screen_init(void)
{
// Fill screen with spaces
memset(Screen, ' ', 1000);
// Bottom and top row
for(byte x=0; x<40; x++)
{
screen_put(x, 0, 0xa0, VCOL_LT_GREY);
screen_put(x, 24, 0xa0, VCOL_LT_GREY);
}
// Left and right column
for(byte y=0; y<25; y++)
{
screen_put( 0, y, 0xa0, VCOL_LT_GREY);
screen_put( 39, y, 0xa0, VCOL_LT_GREY);
}
}
// Initialize a snake
void snake_init(Snake * s)
{
// Length of tail is one
s->length = 1;
s->pos = 0;
// Snake in the center of screen
s->head.x = 20;
s->head.y = 12;
// Starting to the right
s->dir.x = 1;
s->dir.y = 0;
// Show head
screen_put(s->head.x, s->head.y, 81, VCOL_WHITE);
}
bool snake_advance(Snake * s)
{
// Promote head to start of tail
s->tail[s->pos] = s->head;
s->pos++;
screen_put(s->head.x, s->head.y, 81, VCOL_LT_BLUE);
// Advance head
s->head.x += s->dir.x;
s->head.y += s->dir.y;
// Get character at new head position
char ch = screen_get(s->head.x, s->head.y);
// Draw head
screen_put(s->head.x, s->head.y, 81, VCOL_WHITE);
// Clear tail
char tpos = s->pos - s->length;
screen_put(s->tail[tpos].x, s->tail[tpos].y, ' ', VCOL_BLACK);
// Did snake collect the fruit
if (ch == 83)
{
// Extend tail
s->length++;
screen_fruit();
}
else if (ch != ' ')
{
// Snake collided with something
return true;
}
return false;
}
// flash the snake after collision
void snake_flash(Snake * s, char c)
{
// Loop over all tail elements
for(char i=0; i<s->length; i++)
{
// Set color
char tpos = s->pos - i - 1;
screen_put(s->tail[tpos].x, s->tail[tpos].y, 81, c);
}
}
// Change snake direction based on user input
void snake_control(Snake * s, sbyte jx, sbyte jy)
{
// First change from horizontal to vertical, otherwise
// check vertical to horizontal
if (s->dir.x && jy)
{
s->dir.x = 0;
s->dir.y = jy;
}
else if (s->dir.y && jx)
{
s->dir.y = 0;
s->dir.x = jx;
}
}
void game_state(GameState state)
{
// Set new state
TheGame.state = state;
switch(state)
{
case GS_READY:
// Clear the screen
screen_init();
TheGame.count = 32;
break;
case GS_PLAYING:
// Init the snake
snake_init(&TheGame.snake);
// Initial fruit
screen_fruit();
TheGame.count = 16;
break;
case GS_COLLIDE:
TheGame.count = 16;
break;
}
}
// Colors for collision "animation"
char FlashColors[] = {
VCOL_YELLOW,
VCOL_WHITE,
VCOL_LT_GREY,
VCOL_YELLOW,
VCOL_ORANGE,
VCOL_RED,
VCOL_MED_GREY,
VCOL_DARK_GREY
};
// Main game loop, invoked every vsync
void game_loop(void)
{
switch (TheGame.state)
{
case GS_READY:
// Countdown ready to start
if (!--TheGame.count)
game_state(GS_PLAYING);
break;
case GS_PLAYING:
// Check player input on every frame
joy_poll(0);
snake_control(&TheGame.snake, joyx[0], joyy[0]);
if (!--TheGame.count)
{
// Move snake every four frames, advance to collision
// state if collided
if (snake_advance(&TheGame.snake))
game_state(GS_COLLIDE);
else
TheGame.count = 4;
}
break;
case GS_COLLIDE:
// Flash the collided snake
snake_flash(&TheGame.snake, FlashColors[(16 - TheGame.count) / 2]);
if (!--TheGame.count)
game_state(GS_READY);
break;
}
}
int main(void)
{
// Screen color to black
vic.color_border = VCOL_BLACK;
vic.color_back = VCOL_BLACK;
// Start the game in ready state
game_state(GS_READY);
// Forever
for(;;)
{
// One game loop iteration
game_loop();
// Wait one vsync
vic_waitFrame();
}
// Never reached
return 0;
}
+95
View File
@@ -0,0 +1,95 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen, Brush;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x10, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
int poly_x[] = {0, 32, 32, 24, 40, 32, 32, 64, 52, 42, 22, 12};
int poly_y[] = {64, 0, 20, 36, 36, 20, 0, 64, 64, 44, 44, 64};
struct BlitDemo
{
const char * name;
BlitOp op;
};
BlitDemo blitDemos[11] = {
{"SET", BLTOP_SET},
{"RESET", BLTOP_RESET},
{"NOT", BLTOP_NOT},
{"XOR", BLTOP_XOR},
{"OR", BLTOP_OR},
{"AND", BLTOP_AND},
{"NAND", BLTOP_AND_NOT},
{"COPY", BLTOP_COPY},
{"NCOPY", BLTOP_NCOPY},
{"PATTERN", BLTOP_PATTERN},
{"MASKPAT", BLTOP_PATTERN_AND_SRC},
};
char pat[] = {0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00};
int main(void)
{
init();
bm_alloc(&Brush, 8, 8);
bm_fill(&Brush, 0);
ClipRect bcr = {0, 0, 64, 64};
bm_polygon_nc_fill(&Brush, &bcr, poly_x, poly_y, 12, NineShadesOfGrey[8]);
bmu_rect_pattern(&Screen, 0, 0, 320, 200, NineShadesOfGrey[2]);
ClipRect scr = {0, 0, 320, 200};
for(int i=0; i<11; i++)
{
int dx = 80 * ((i + 1) % 4);
int dy = 66 * ((i + 1) / 4);
bmu_bitblit(&Screen, dx + 8, dy + 1, &Brush, 0, 0, 64, 64, pat, blitDemos[i].op);
bm_put_string(&Screen, &scr, dx + 8, dy + 20, blitDemos[i].name, BLTOP_COPY);
}
done();
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
../../bin/oscar64 splitscreen.c
../../bin/oscar64 func3d.c -n
../../bin/oscar64 lines.c -n
../../bin/oscar64 polygon.c -n
../../bin/oscar64 bitblit.c -n
../../bin/oscar64 cube3d.c -n
../../bin/oscar64 fractaltree.c -n
../../bin/oscar64 qsort.c -n
+222
View File
@@ -0,0 +1,222 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#include <stdio.h>
#include <gfx/vector3d.h>
#include <math.h>
#include <fixmath.h>
char * const Color = (char *)0xd000;
char * const Hires = (char *)0xe000;
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x01, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
// getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
ClipRect cr = {0, 0, 320, 200};
struct Point
{
int x, y;
};
__striped Point tcorners[8], pcorners[8];
void drawCube(void)
{
for(char i=0; i<8; i++)
{
if (!(i & 1))
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 1].x, tcorners[i | 1].y, 0xff, LINOP_OR);
if (!(i & 2))
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 2].x, tcorners[i | 2].y, 0xff, LINOP_OR);
if (!(i & 4))
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 4].x, tcorners[i | 4].y, 0xff, LINOP_OR);
pcorners[i] = tcorners[i];
}
}
void hideCube(void)
{
for(char i=0; i<8; i++)
{
if (!(i & 1))
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 1].x, pcorners[i | 1].y, 0xff, LINOP_AND);
if (!(i & 2))
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 2].x, pcorners[i | 2].y, 0xff, LINOP_AND);
if (!(i & 4))
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 4].x, pcorners[i | 4].y, 0xff, LINOP_AND);
}
}
void xorCube(void)
{
for(char i=0; i<8; i++)
{
if (!(i & 1))
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 1].x, tcorners[i | 1].y, 0xff, LINOP_XOR);
if (!(i & 2))
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 2].x, tcorners[i | 2].y, 0xff, LINOP_XOR);
if (!(i & 4))
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 4].x, tcorners[i | 4].y, 0xff, LINOP_XOR);
pcorners[i] = tcorners[i];
}
}
void xor2Cube(void)
{
for(char i=0; i<8; i++)
{
if (!(i & 1))
{
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 1].x, pcorners[i | 1].y, 0xff, LINOP_XOR);
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 1].x, tcorners[i | 1].y, 0xff, LINOP_XOR);
}
if (!(i & 2))
{
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 2].x, pcorners[i | 2].y, 0xff, LINOP_XOR);
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 2].x, tcorners[i | 2].y, 0xff, LINOP_XOR);
}
if (!(i & 4))
{
bm_line(&Screen, &cr, pcorners[i].x, pcorners[i].y, pcorners[i | 4].x, pcorners[i | 4].y, 0xff, LINOP_XOR);
bm_line(&Screen, &cr, tcorners[i].x, tcorners[i].y, tcorners[i | 4].x, tcorners[i | 4].y, 0xff, LINOP_XOR);
}
}
for(char i=0; i<8; i++)
pcorners[i] = tcorners[i];
}
#if 1
F12Vector3 corners[8];
F12Matrix3 rmat, tmat;
int main(void)
{
init();
for(char i=0; i<8; i++)
{
corners[i].v[0] = (i & 1) ? -FIX12_ONE : FIX12_ONE;
corners[i].v[1] = (i & 2) ? -FIX12_ONE : FIX12_ONE;
corners[i].v[2] = (i & 4) ? -FIX12_ONE : FIX12_ONE;
}
for(int k=0; k<100; k++)
{
f12mat3_set_rotate_x(&rmat, 0.1 * k);
f12mat3_set_rotate_y(&tmat, 0.06 * k);
f12mat3_mmul(&rmat, &tmat);
for(char i=0; i<8; i++)
{
F12Vector3 vd;
f12vec3_mmul(&vd, &rmat, corners + i);
tcorners[i].x = lmuldiv16s(vd.v[0], 140, vd.v[2] + 4 * FIX12_ONE) + 160;
tcorners[i].y = lmuldiv16s(vd.v[1], 140, vd.v[2] + 4 * FIX12_ONE) + 100;
}
#if 1
if (k)
xor2Cube();
else
xorCube();
#else
hideCube();
drawCube();
#endif
}
done();
return 0;
}
#else
Matrix4 wmat, pmat, tmat, rmat;
Vector3 corners[8];
int main(void)
{
init();
mat4_ident(&wmat);
mat4_make_perspective(&pmat, 0.5 * PI, 1.0, 0.0, 200.0);
mat4_scale(&wmat, 1);
for(char i=0; i<8; i++)
{
vec3_set(corners + i,
(i & 1) ? -1.0 : 1.0,
(i & 2) ? -1.0 : 1.0,
(i & 4) ? -1.0 : 1.0);
}
for(int k=0; k<100; k++)
{
mat4_set_rotate_x(&rmat, 0.1 * k);
mat4_set_rotate_y(&tmat, 0.06 * k);
mat4_rmmul(&rmat, &tmat);
mat4_rmmul(&rmat, &wmat);
rmat.m[14] += 4.0;
tmat = pmat;
mat4_mmul(&tmat, &rmat);
for(char i=0; i<8; i++)
{
Vector3 vd;
vec3_project(&vd, &rmat, corners + i);
tcorners[i].x = (int)(vd.v[0] * 100) + 160;
tcorners[i].y = (int)(vd.v[1] * 100) + 100;
}
hideCube();
drawCube();
}
done();
return 0;
}
#endif
+64
View File
@@ -0,0 +1,64 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <math.h>
#include <string.h>
#include <conio.h>
char * const Color = (char *)0xd000;
char * const Hires = (char *)0xe000;
Bitmap Screen;
ClipRect Clip = {0, 0, 320, 200};
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x01, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
void draw(float x, float y, float a, float s)
{
if (s < 6.0)
return;
float tx = x + cos(a) * s;
float ty = y + sin(a) * s;
bm_line(&Screen, &Clip, x, y, tx, ty, 0xff, LINOP_SET);
draw(tx, ty, a + 0.3, s * 0.9);
draw(tx, ty, a - 0.4, s * 0.8);
}
int main(void)
{
init();
draw(140, 199, PI * 1.5, 32);
done();
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

+231
View File
@@ -0,0 +1,231 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#include <gfx/vector3d.h>
#include <gfx/bitmap.h>
#include <stdio.h>
#pragma stacksize(1024)
#pragma region(main, 0x0a00, 0xc800, , , {code, data, bss, heap, stack} )
#define Color ((char *)0xc800)
#define Hires ((char *)0xe000)
Bitmap Screen = {
Hires, nullptr, 40, 25, 320
};
ClipRect SRect = {
0, 0, 320, 200
};
char chk[] = {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55};
char white[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
char black[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Matrix4 wmat, pmat, tmat, rmat;
Vector3 vlight;
void init(void)
{
mmap_set(MMAP_NO_BASIC);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_back = VCOL_WHITE;
vic.color_border = VCOL_WHITE;
mmap_trampoline();
mmap_set(MMAP_NO_ROM);
memset(Color, 0x01, 1000);
memset(Hires, 0, 8000);
}
void restore(void)
{
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
mmap_set(MMAP_ROM);
}
struct Point
{
int x, y;
};
#define HALF 15
#define FULL (HALF + HALF)
#define SIZE (FULL + 1)
#define QFULL (FULL * FULL)
Vector3 v[SIZE][SIZE];
Point p[SIZE][SIZE];
float z[SIZE][SIZE];
struct Surf
{
float z;
char x, y;
} surfs[QFULL];
void qsort(Surf * n, int s)
{
if (s > 1)
{
Surf pn = n[0];
int pi = 0;
for(int i=1; i<s; i++)
{
if (n[i].z > pn.z)
{
n[pi] = n[i];
pi++;
n[i] = n[pi];
}
}
n[pi] = pn;
qsort(n, pi);
qsort(n + pi + 1, s - pi - 1);
}
}
int main(void)
{
init();
bm_put_string(&Screen, &SRect, 0, 0, "Preparing function", BLTOP_COPY);
mat4_ident(&wmat);
mat4_make_perspective(&pmat, 0.5 * PI, 1.0, 0.0, 200.0);
for(int ix=0; ix<SIZE; ix++)
{
for(int iy=0; iy<SIZE; iy++)
{
float x = (ix - HALF) * (1.0 / HALF), y = (HALF - iy) * (1.0 / HALF);
float r = sqrt(x * x + y * y);
float f = - cos(r * 16) * exp(- 2 * r);
vec3_set(&(v[iy][ix]), x, f * 0.5, y);
}
}
bm_put_string(&Screen, &SRect, 0, 8, "Projecting vertices", BLTOP_COPY);
vec3_set(&vlight, 2.0, -2.0, -1.0);
vec3_norm(&vlight);
mat4_scale(&wmat, 18);
mat4_set_rotate_x(&rmat, -0.98);
mat4_set_rotate_y(&tmat, 0.3);
mat4_rmmul(&rmat, &tmat);
mat4_rmmul(&rmat, &wmat);
rmat.m[14] += 20.0;
tmat = pmat;
mat4_mmul(&tmat, &rmat);
for(int ix=0; ix<SIZE; ix++)
{
for(int iy=0; iy<SIZE; iy++)
{
Vector3 vp;
vec3_project(&vp, &tmat, &(v[iy][ix]));
p[iy][ix].x = vp.v[0] * 140 + 160;
p[iy][ix].y = vp.v[1] * 140 + 80;
z[iy][ix] = vp.v[2];
}
}
bm_put_string(&Screen, &SRect, 0, 16, "Sorting surfaces", BLTOP_COPY);
for(int iy=0; iy<FULL; iy++)
{
for(int ix=0; ix<FULL; ix++)
{
surfs[FULL * iy + ix].z =
z[iy + 0][ix + 0] +
z[iy + 0][ix + 1] +
z[iy + 1][ix + 0] +
z[iy + 1][ix + 1];
surfs[FULL * iy + ix].x = ix;
surfs[FULL * iy + ix].y = iy;
}
}
qsort(surfs, QFULL);
bm_put_string(&Screen, &SRect, 0, 24, "Drawing surfaces", BLTOP_COPY);
for(int i=0; i< QFULL; i++)
{
char ix = surfs[i].x, iy = surfs[i].y;
Vector3 d0, d1, n;
vec3_diff(&d0, &(v[iy + 0][ix + 0]), &(v[iy + 1][ix + 1]));
vec3_diff(&d1, &(v[iy + 1][ix + 0]), &(v[iy + 0][ix + 1]));
vec3_xmul(&n, &d0, &d1);
vec3_norm(&n);
float f = vec3_vmul(&vlight, &n);
int c = 8;
char patt = 0xaa;
if (f > 0)
{
c = 8 - (int)(f * 9);
if (c < 5)
patt = 0xff;
}
bm_quad_fill(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y,
NineShadesOfGrey[c]);
bm_line(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y, patt, LINOP_SET);
bm_line(&Screen, &SRect,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt, LINOP_SET);
bm_line(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y, patt, LINOP_SET);
bm_line(&Screen, &SRect,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt, LINOP_SET);
}
mmap_set(MMAP_NO_BASIC);
getch();
restore();
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+68
View File
@@ -0,0 +1,68 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x01, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
void draw(ClipRect * cr, byte pattern)
{
for(int i=0; i<40; i ++)
{
bm_line(&Screen, cr, 8 * i, 0, 319, 5 * i, pattern, LINOP_SET);
bm_line(&Screen, cr, 319, 5 * i, 319 - 8 * i, 199, pattern, LINOP_SET);
bm_line(&Screen, cr, 319 - 8 * i, 199, 0, 199 - 5 * i, pattern, LINOP_SET);
bm_line(&Screen, cr, 0, 199 - 5 * i, 8 * i, 0, pattern, LINOP_SET);
}
}
int main(void)
{
init();
ClipRect cr = {0, 0, 320, 200};
draw(&cr, 0xff);
draw(&cr, 0x00);
draw(&cr, 0xff);
draw(&cr, 0xaa);
draw(&cr, 0x88);
draw(&cr, 0x80);
draw(&cr, 0x00);
done();
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
call ..\..\bin\oscar64 splitscreen.c
call ..\..\bin\oscar64 func3d.c -n
call ..\..\bin\oscar64 lines.c -n
call ..\..\bin\oscar64 polygon.c -n
call ..\..\bin\oscar64 bitblit.c -n
call ..\..\bin\oscar64 cube3d.c -n
call ..\..\bin\oscar64 fractaltree.c -n
call ..\..\bin\oscar64 qsort.c -n
+11
View File
@@ -0,0 +1,11 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: splitscreen.prg func3d.prg lines.prg polygon.prg bitblit.prg cube3d.prg fractaltree.prg qsort.prg
splitscreen.prg: splitscreen.c
@$(OSCAR64_CC) $<
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg *.bcs
+83
View File
@@ -0,0 +1,83 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x10, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
int main(void)
{
init();
bmu_rect_pattern(&Screen, 0, 0, 320, 200, NineShadesOfGrey[4]);
bmu_rect_clear(&Screen, 14, 14, 304, 184);
bmu_rect_fill(&Screen, 8, 8, 304, 184);
bmu_rect_clear(&Screen, 10, 10, 300, 180);
ClipRect cr = {11, 11, 309, 189};
float px[10], py[10];
for(int i=0; i<10; i++)
{
float w = i * PI / 5, c = cos(w), s = sin(w), r = (i & 1) ? 1.0 : 0.4;
px[i] = r * c; py[i] = r * s;
}
for(int i=0; i<128; i++)
{
int rpx[10], rpy[10];
float r = i + 4;
float w = i * PI / 16, c = r * cos(w), s = r * sin(w), cw = r * cos(w * 2.0), sw = r * sin(w * 2.0);
for(int j=0; j<10; j++)
{
float fx = px[j], fy = py[j];
rpx[j] = 160 + cw + fx * c + fy * s;
rpy[j] = 100 + sw - fx * s + fy * c;
}
bm_polygon_nc_fill(&Screen, &cr, rpx, rpy, 10, NineShadesOfGrey[i % 9]);
for(int j=0; j<10; j++)
{
int k = (j + 1) % 10;
bm_line(&Screen, &cr, rpx[j], rpy[j], rpx[k], rpy[k], 0xff, LINOP_SET);
}
}
done();
return 0;
}
+117
View File
@@ -0,0 +1,117 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x01, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
char field[160];
void fill(void)
{
for(int i=0; i<160; i++)
field[i] = i;
}
void shuffle(void)
{
for(int i=0; i<160; i++)
{
int j = rand() % 160;
char t = field[i];
field[i] = field[j];
field[j] = t;
}
}
void draw(unsigned i)
{
bmu_line(&Screen, 2 * i, 0, 2 * i, field[i], 0x00, LINOP_SET);
bmu_line(&Screen, 2 * i, field[i], 2 * i, 160, 0xff, LINOP_SET);
}
void partition(int l, int r)
{
while (l < r)
{
int i = l;
int j = r;
char pi = field[(r + l) >> 1];
while (i <= j)
{
while (field[i] > pi)
i++;
while (field[j] < pi)
j--;
if (i <= j)
{
char t = field[i];
field[i] = field[j];
field[j] = t;
draw(i);
draw(j);
i++;
j--;
}
}
partition(l, j);
l = i;
}
}
int main(void)
{
init();
fill();
shuffle();
for(int i=0; i<160; i++)
draw(i);
clock_t t0 = clock();
partition(0, 159);
clock_t t1 = clock();
char t[20];
sprintf(t, "TIME : %.1f SECS.", (float)(t1 - t0) / 60);
bmu_put_chars(&Screen, 4, 170, t, strlen(t), BLTOP_COPY);
done();
return 0;
}
+101
View File
@@ -0,0 +1,101 @@
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <c64/rasterirq.h>
#include <c64/memmap.h>
#include <string.h>
#include <stdio.h>
#include <c64/charwin.h>
#define Color ((char *)0xc800)
#define Hires ((char *)0xe000)
char white[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
char check[] = {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
char black[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Bitmap Screen;
RIRQCode rirqtop, rirqbottom;
#pragma align(rirqtop, 32)
#pragma align(rirqbottom, 32)
CharWin twin;
CharWin ewin;
int main(void)
{
mmap_trampoline();
mmap_set(MMAP_CHAR_ROM);
memcpy((char *)0xd000, (char *)0xd000, 4096);
mmap_set(MMAP_NO_ROM);
rirq_init(true);
vic.color_back = VCOL_BLACK;
memset(Color, 0x10, 1000);
memset(Hires, 0, 8000);
vic_setmode(VICM_HIRES, Color, Hires);
rirq_build(&rirqtop, 2);
rirq_write(&rirqtop, 0, &vic.memptr, 0x28);
rirq_write(&rirqtop, 1, &vic.ctrl1, VIC_CTRL1_BMM | VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
rirq_build(&rirqbottom, 3);
rirq_delay(&rirqbottom, 10);
rirq_write(&rirqbottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
rirq_write(&rirqbottom, 2, &vic.memptr, 0x26);
rirq_set(0, 10, &rirqtop);
rirq_set(1, 49 + 8 * 20, &rirqbottom);
rirq_sort();
rirq_start();
bm_init(&Screen, Hires, 40, 25);
bmu_rect_pattern(&Screen, 0, 0, 320, 160, check);
bmu_rect_fill(&Screen, 0, 159, 320, 1);
bmu_rect_clear(&Screen, 0, 158, 320, 1);
cwin_init(&twin, Color, 0, 20, 40, 4);
cwin_init(&ewin, Color, 0, 24, 40, 1);
ClipRect rect = {0, 0, 320, 158};
cwin_clear(&twin);
cwin_putat_string(&twin, 0, 0, p"Enter x, y and radius for circle", 0x07);
for(;;)
{
cwin_clear(&ewin);
cwin_cursor_move(&ewin, 0, 0);
mmap_set(MMAP_NO_BASIC);
cwin_edit(&ewin);
mmap_set(MMAP_RAM);
char str[40];
cwin_read_string(&ewin, str);
int n, x, y, r;
n = sscanf(str, "%d %d %d", &x, &y, &r);
cwin_putat_string(&twin, 0, 1, str, 0x0e);
sprintf(str, p"N: %d X: %3d Y: %3d R: %2d", n, x, y, r);
cwin_putat_string(&twin, 0, 2, str, 0x07);
if (n == 3)
{
bm_circle_fill(&Screen, &rect, x, y, r + 1, black);
bm_circle_fill(&Screen, &rect, x, y, r - 1, white);
}
}
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
../../bin/oscar64 func3d.c -n
../../bin/oscar64 polygon.c -n
../../bin/oscar64 floodfill.c -n
../../bin/oscar64 paint.c -n
+55
View File
@@ -0,0 +1,55 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <gfx/mcbitmap.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#pragma region(main, 0x0a00, 0xc800, , , {code, data, bss, heap, stack} )
#define Color1 ((char *)0xc800)
#define Color2 ((char *)0xd800)
#define Hires ((char *)0xe000)
Bitmap sbm;
int main(void)
{
mmap_trampoline();
vic_setmode(VICM_HIRES_MC, Color1, Hires);
mmap_set(MMAP_NO_ROM);
vic.color_back = VCOL_BLACK;
vic.color_border = VCOL_BLACK;
memset(Color1, 0x67, 1000);
memset(Color2, 0x02, 1000);
memset(Hires, 0, 8000);
bm_init(&sbm, Hires, 40, 25);
ClipRect scr = { 0, 0, 320, 200 };
for(;;)
{
for(int i=0; i<20; i++)
{
bmmc_circle_fill(&sbm, &scr, rand() % 320, rand() % 200, 5 + rand() % 40, MixedColors[1][1]);
}
for(int i=0; i<20; i++)
{
bmmc_circle_fill(&sbm, &scr, rand() % 320, rand() % 200, 5 + rand() % 40, MixedColors[0][0]);
}
bmmc_flood_fill(&sbm, &scr, 210, 100, 2);
bmmc_flood_fill(&sbm, &scr, 60, 140, 3);
}
mmap_set(MMAP_ROM);
getch();
return 0;
}
+228
View File
@@ -0,0 +1,228 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#include <gfx/vector3d.h>
#include <gfx/mcbitmap.h>
#include <stdio.h>
#pragma region(main, 0x0a00, 0xc800, , , {code, data, bss, heap, stack} )
#define Color1 ((char *)0xc800)
#define Color2 ((char *)0xd800)
#define Hires ((char *)0xe000)
Bitmap Screen = {
Hires, nullptr, 40, 25, 320
};
ClipRect SRect = {
0, 0, 320, 200
};
Matrix4 wmat, pmat, tmat, rmat;
Vector3 vlight;
void init(void)
{
mmap_set(MMAP_NO_BASIC);
vic_setmode(VICM_HIRES_MC, Color1, Hires);
vic.color_back = VCOL_DARK_GREY;
vic.color_border = VCOL_DARK_GREY;
mmap_trampoline();
mmap_set(MMAP_NO_ROM);
memset(Color1, 0xcf, 1000);
memset(Color2, 0x01, 1000);
memset(Hires, 0, 8000);
}
void restore(void)
{
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
mmap_set(MMAP_ROM);
}
struct Point
{
int x, y;
};
#define HALF 15
#define FULL (HALF + HALF)
#define SIZE (FULL + 1)
#define QFULL (FULL * FULL)
Vector3 v[SIZE][SIZE];
Point p[SIZE][SIZE];
float z[SIZE][SIZE];
struct Surf
{
float z;
char x, y;
} surfs[QFULL];
void qsort(Surf * n, int s)
{
if (s > 1)
{
Surf pn = n[0];
int pi = 0;
for(int i=1; i<s; i++)
{
if (n[i].z > pn.z)
{
n[pi] = n[i];
pi++;
n[i] = n[pi];
}
}
n[pi] = pn;
qsort(n, pi);
qsort(n + pi + 1, s - pi - 1);
}
}
int main(void)
{
init();
bm_put_string(&Screen, &SRect, 0, 0, "Preparing function", BLTOP_COPY);
mat4_ident(&wmat);
mat4_make_perspective(&pmat, 0.5 * PI, 1.0, 0.0, 200.0);
for(int ix=0; ix<SIZE; ix++)
{
for(int iy=0; iy<SIZE; iy++)
{
float x = (ix - HALF) * (1.0 / HALF), y = (HALF - iy) * (1.0 / HALF);
float r = sqrt(x * x + y * y);
float f = - cos(r * 16) * exp(- 2 * r);
vec3_set(&(v[iy][ix]), x, f * 0.5, y);
}
}
bm_put_string(&Screen, &SRect, 0, 8, "Projecting vertices", BLTOP_COPY);
vec3_set(&vlight, 2.0, -2.0, -1.0);
vec3_norm(&vlight);
mat4_scale(&wmat, 18);
mat4_set_rotate_x(&rmat, -0.98);
mat4_set_rotate_y(&tmat, 0.3);
mat4_rmmul(&rmat, &tmat);
mat4_rmmul(&rmat, &wmat);
rmat.m[14] += 20.0;
tmat = pmat;
mat4_mmul(&tmat, &rmat);
for(int ix=0; ix<SIZE; ix++)
{
for(int iy=0; iy<SIZE; iy++)
{
Vector3 vp;
vec3_project(&vp, &tmat, &(v[iy][ix]));
p[iy][ix].x = vp.v[0] * 140 + 160;
p[iy][ix].y = vp.v[1] * 140 + 80;
z[iy][ix] = vp.v[2];
}
}
bm_put_string(&Screen, &SRect, 0, 16, "Sorting surfaces", BLTOP_COPY);
for(int iy=0; iy<FULL; iy++)
{
for(int ix=0; ix<FULL; ix++)
{
surfs[FULL * iy + ix].z =
z[iy + 0][ix + 0] +
z[iy + 0][ix + 1] +
z[iy + 1][ix + 0] +
z[iy + 1][ix + 1];
surfs[FULL * iy + ix].x = ix;
surfs[FULL * iy + ix].y = iy;
}
}
qsort(surfs, QFULL);
bm_put_string(&Screen, &SRect, 0, 24, "Drawing surfaces", BLTOP_COPY);
for(int i=0; i< QFULL; i++)
{
char ix = surfs[i].x, iy = surfs[i].y;
Vector3 d0, d1, n;
vec3_diff(&d0, &(v[iy + 0][ix + 0]), &(v[iy + 1][ix + 1]));
vec3_diff(&d1, &(v[iy + 1][ix + 0]), &(v[iy + 0][ix + 1]));
vec3_xmul(&n, &d0, &d1);
vec3_norm(&n);
float f = vec3_vmul(&vlight, &n);
int c = 0;
char patt = 3;
if (f > 0)
{
c = 1 + (int)(f * 6);
if (c > 4)
patt = 0;
}
bmmc_quad_fill(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y,
MixedColors[c >> 1][(c + 1) >> 1]);
#if 0
bmmc_line(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y, patt);
bmmc_line(&Screen, &SRect,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt);
bmmc_line(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y, patt);
bmmc_line(&Screen, &SRect,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt);
#endif
}
mmap_set(MMAP_NO_BASIC);
getch();
restore();
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
call ..\..\bin\oscar64 floodfill.c -n
call ..\..\bin\oscar64 polygon.c -n
call ..\..\bin\oscar64 func3d.c -n
call ..\..\bin\oscar64 paint.c -n
+8
View File
@@ -0,0 +1,8 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: func3d.prg polygon.prg floodfill.prg paint.prg
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg
+181
View File
@@ -0,0 +1,181 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <gfx/mcbitmap.h>
#include <c64/mouse.h>
#include <c64/joystick.h>
#include <c64/keyboard.h>
#include <c64/cia.h>
#include <c64/sprites.h>
#include <string.h>
#include <oscar.h>
#pragma region(main, 0x0880, 0xd000, , , {code, data, bss, heap, stack} )
static char * const Color1 = (char *)0xd000;
static char * const Color2 = (char *)0xd800;
static char * const Hires = (char *)0xe000;
static char * const Sprites = (char *)0xd800;
const char MouseSpriteData[] = {
#embed spd_sprites lzo "../resources/mouse.spd"
};
Bitmap sbm;
ClipRect scr = { 0, 0, 320, 200 };
void init(void)
{
// Install IRQ trampoline
mmap_trampoline();
cia_init();
// All RAM
mmap_set(MMAP_RAM);
// Init hires mem, and resources
memset(Color1, 0x67, 1000);
memset(Hires, 0, 8000);
oscar_expand_lzo(Sprites, MouseSpriteData);
// Sprite image for cursor
Color1[0x3f8] = 97;
Color1[0x3f9] = 96;
// Enable IO space
mmap_set(MMAP_NO_ROM);
// Clear color RAM
memset(Color2, 0x02, 1000);
// Set screen
vic.color_back = VCOL_BLACK;
vic.color_border = VCOL_BLACK;
vic_setmode(VICM_HIRES_MC, Color1, Hires);
// Init mouse cursor
spr_show(0, true);
spr_show(1, true);
spr_color(0, VCOL_BLACK);
spr_color(1, VCOL_WHITE);
spr_move(0, 24, 50);
spr_move(1, 24, 50);
// Disable system interrupt and init mouse
mouse_init();
bm_init(&sbm, Hires, 40, 25);
}
int mouse_x, mouse_y;
bool mouse_move(void)
{
// Poll mouse and joystick for backup
joy_poll(0);
mouse_poll();
// New mouse cursor position
int mx = mouse_x + (signed char)(joyx[0] + mouse_dx);
int my = mouse_y + (signed char)(joyy[0] - mouse_dy);
// Clip to screen
if (mx < 0)
mx = 0;
else if (mx > 319)
mx = 319;
if (my < 0)
my = 0;
else if (my > 199)
my = 199;
// Check if moved
if (mx != mouse_x || my != mouse_y)
{
mouse_x = mx;
mouse_y = my;
// Update cursor sprite
spr_move(0, mx + 24, my + 50);
spr_move(1, mx + 24, my + 50);
return true;
}
return false;
}
int main(void)
{
init();
char c0 = 1, c1 = 1;
for(;;)
{
// Check if mouse moved
if (mouse_move())
{
// Paint a circle at the mouse position, if mouse was moved
if (mouse_lb || joyb[0])
bmmc_circle_fill(&sbm, &scr, mouse_x, mouse_y, 5, MixedColors[c0][c1]);
else if (mouse_rb)
bmmc_circle_fill(&sbm, &scr, mouse_x, mouse_y, 5, MixedColors[0][0]);
}
// Poll the keyboard
keyb_poll();
switch (keyb_key)
{
// Clear screen
case KSCAN_HOME + KSCAN_QUAL_DOWN:
bmmcu_rect_fill(&sbm, 0, 0, 320, 200, 0);
break;
// Select color with 0..9
case KSCAN_0 + KSCAN_QUAL_DOWN:
c0 = 0; c1 = 0;
break;
case KSCAN_1 + KSCAN_QUAL_DOWN:
c0 = 1; c1 = 1;
break;
case KSCAN_2 + KSCAN_QUAL_DOWN:
c0 = 2; c1 = 2;
break;
case KSCAN_3 + KSCAN_QUAL_DOWN:
c0 = 3; c1 = 3;
break;
case KSCAN_4 + KSCAN_QUAL_DOWN:
c0 = 1; c1 = 0;
break;
case KSCAN_5 + KSCAN_QUAL_DOWN:
c0 = 1; c1 = 2;
break;
case KSCAN_6 + KSCAN_QUAL_DOWN:
c0 = 1; c1 = 3;
break;
case KSCAN_7 + KSCAN_QUAL_DOWN:
c0 = 2; c1 = 0;
break;
case KSCAN_8 + KSCAN_QUAL_DOWN:
c0 = 2; c1 = 3;
break;
case KSCAN_9 + KSCAN_QUAL_DOWN:
c0 = 3; c1 = 0;
break;
// Flood fill
case KSCAN_F + KSCAN_QUAL_DOWN:
bmmc_flood_fill(&sbm, &scr, mouse_x, mouse_y, c0);
break;
}
// Wait one frame
vic_waitFrame();
}
return 0;
}
+86
View File
@@ -0,0 +1,86 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/mcbitmap.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#define Color1 ((char *)0xc800)
#define Color2 ((char *)0xd800)
#define Hires ((char *)0xe000)
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color1, 0x67, 1000);
memset(Color2, 0x02, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES_MC, Color1, Hires);
vic.color_back = VCOL_BLACK;
vic.color_border = VCOL_BLACK;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
int main(void)
{
init();
bmmcu_rect_fill(&Screen, 0, 0, 320, 200, 1);
bmmcu_rect_fill(&Screen, 8, 8, 304, 184, 2);
bmmcu_rect_fill(&Screen, 10, 10, 300, 180, 0);
ClipRect cr = {10, 10, 310, 190};
float px[10], py[10];
for(int i=0; i<10; i++)
{
float w = i * PI / 5, c = cos(w), s = sin(w), r = (i & 1) ? 1.0 : 0.4;
px[i] = r * c; py[i] = r * s;
}
for(int i=0; i<128; i++)
{
int rpx[10], rpy[10];
float r = i + 4;
float w = i * PI / 16, c = r * cos(w), s = r * sin(w), cw = r * cos(w * 2.0), sw = r * sin(w * 2.0);
for(int j=0; j<10; j++)
{
float fx = px[j], fy = py[j];
rpx[j] = 160 + cw + fx * c + fy * s;
rpy[j] = 100 + sw - fx * s + fy * c;
}
bmmc_polygon_nc_fill(&Screen, &cr, rpx, rpy, 10, MixedColors[i & 3][(i >> 2) & 3]);
for(int j=0; j<10; j++)
{
int k = (j + 1) % 10;
bmmc_line(&Screen, &cr, rpx[j], rpy[j], rpx[k], rpy[k], 0);
}
}
done();
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
../../bin/oscar64 diskdir.c
../../bin/oscar64 filewrite.c
../../bin/oscar64 fileread.c
../../bin/oscar64 charwrite.c
../../bin/oscar64 charread.c
../../bin/oscar64 hireswrite.c
../../bin/oscar64 hiresread.c
+28
View File
@@ -0,0 +1,28 @@
#include <stdio.h>
#include <c64/kernalio.h>
int main(void)
{
// Set name for file and open it on drive 9
krnio_setnam("@0:CHARS,P,R");
if (krnio_open(2, 9, 2))
{
// Read bytes until failure
int ch, k = 0;
while ((ch = krnio_getch(2)) >= 0)
{
// Print the value of the byte
printf("%d : %d\n", k, ch);
k++;
// Exit the loop if this was the last byte of the file
if (ch & 0x100)
break;
}
// Close the file
krnio_close(2);
}
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
#include <stdio.h>
#include <c64/kernalio.h>
int main(void)
{
// Set name for file and open it with replace on drive 9
krnio_setnam("@0:CHARS,P,W");
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++)
krnio_putch(2, i);
// Close the file again
krnio_close(2);
}
return 0;
}
+64
View File
@@ -0,0 +1,64 @@
#include <stdio.h>
#include <c64/kernalio.h>
int main(void)
{
// Set name for directory
krnio_setnam("$");
// Open #2 on drive 9 (or 8)
if (krnio_open(2, 9, 0))
{
// Switch input to file #2
if (krnio_chkin(2))
{
// Skip BASIC load address
krnio_chrin();
krnio_chrin();
// Loop while we have more lines
int ch;
while((ch = krnio_chrin()) > 0)
{
unsigned line;
char buff[40];
// Skip second basic link byte
krnio_chrin();
// Read line number (size in blocks)
ch = krnio_chrin();
line = ch;
ch = krnio_chrin();
line += 256 * ch;
// Read file name, reading till end of basic line
int n = 0;
while ((ch = krnio_chrin()) > 0)
buff[n++] = ch;
buff[n] = 0;
// Print size and name
printf("%u %s\n", line, buff);
}
// Reset channels
krnio_clrchn();
}
// Close file #2
krnio_close(2);
}
else
printf("FAIL OPEN %d\n", krnio_status());
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <c64/kernalio.h>
struct Score
{
char name[5];
unsigned score;
};
Score score[4];
int main(void)
{
// Set name for file and open it on drive 9
krnio_setnam("HIGHSCORE,P,R");
if (krnio_open(2, 9, 2))
{
// Read the content of the file into the score arrayx
krnio_read(2, (char*)score, sizeof(score));
// Close the file
krnio_close(2);
}
// Print the result to stdout
for(int i=0; i<4; i++)
{
printf("%s : %u\n", score[i].name, score[i].score);
}
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <c64/kernalio.h>
struct Score
{
char name[5];
unsigned score;
};
Score score[] = {
{"AAA", 10000},
{"BBB", 9000},
{"CCC", 8000},
{"DDD", 4000}
};
int main(void)
{
// Set name for file and open it with replace on drive 9
krnio_setnam("@0:HIGHSCORE,P,W");
if (krnio_open(2, 9, 2))
{
// Fill the file with the score array
krnio_write(2, (char*)score, sizeof(score));
// Close the file
krnio_close(2);
}
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
#include <c64/kernalio.h>
#include <c64/memmap.h>
#include <c64/vic.h>
#include <c64/flossiec.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <stdio.h>
char * const Hires = (char *)0xe000;
char * const Color = (char *)0xd800;
char * const Screen = (char *)0xcc00;
int main(void)
{
// Prepare fast loader in floppy memory
flosskio_init(8);
// Map filenames to track/sector addresses
floss_blk blks[1];
flosskio_mapdir(p"blumba2", blks);
// Clear screen
memset(Hires, 0x00, 8000);
memset(Screen, 0xff, 1000);
memset(Color, 0x01, 1000);
// Switch to multicolor hires
vic_setmode(VICM_HIRES_MC, Screen, Hires);
vic.color_back = VCOL_BLACK;
vic.color_border = VCOL_BLACK;
// Open file
flosskio_open(blks[0].track, blks[0].sector);
// Read compressed image
flossiec_read_lzo(Hires, 8000);
flossiec_read_lzo(Screen, 1000);
flossiec_read_lzo(Color, 1000);
// Close file
flosskio_close();
// Remove drive code
flosskio_shutdown();
// Wait for a character
getchar();
// Restore VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
#include <c64/kernalio.h>
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <stdio.h>
Bitmap Screen;
#define ScreenMem ((char *)0xe000)
#define ColorMem ((char *)0xd000)
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Initialize the display bitmap
bm_init(&Screen, ScreenMem, 40, 25);
// Clear the color memory with ROM and IO disabled
mmap_set(MMAP_RAM);
memset(ScreenMem, 0, 8000);
memset(ColorMem, 0x70, 1000);
mmap_set(MMAP_NO_ROM);
// Switch VIC to hires mode
vic_setmode(VICM_HIRES, ColorMem, ScreenMem);
// Reenable the kernal rom
mmap_set(MMAP_ROM);
// Set name for file and open it with replace on drive 9
krnio_setnam("TESTIMAGE,P,R");
if (krnio_open(2, 9, 2))
{
// Read the bitmap image in one go
krnio_read(2, ScreenMem, 8000);
// Close the file
krnio_close(2);
}
// Wait for a character
getchar();
// Restore VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
+80
View File
@@ -0,0 +1,80 @@
#include <c64/kernalio.h>
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <stdio.h>
Bitmap Screen, Brush;
char Buffer[200];
#define ScreenMem ((char *)0xe000)
#define ColorMem ((char *)0xd000)
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Initialize the display bitmap and a brush
bm_init(&Screen, ScreenMem, 40, 25);
bm_alloc(&Brush, 2, 2);
// Clear the color memory with ROM and IO disabled
mmap_set(MMAP_RAM);
memset(ScreenMem, 0, 8000);
memset(ColorMem, 0x70, 1000);
mmap_set(MMAP_NO_ROM);
// Switch VIC to hires mode
vic_setmode(VICM_HIRES, ColorMem, ScreenMem);
// Draw the brush
ClipRect crb = {0, 0, 16, 16};
bm_fill(&Brush, 0);
bm_circle_fill(&Brush, &crb, 7, 7, 6, NineShadesOfGrey[8]);
// Draw the main image
ClipRect crr = {0, 0, 320, 200};
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, 200, 80, 20, NineShadesOfGrey[0]);
// And a smile
for(int x=-40; x<=40; x+=4)
{
int y = bm_usqrt(50 * 50 - x * x);
bm_bitblit(&Screen, &crr, 160 - 7 + x, 100 + y, &Brush, 0, 0, 15, 15, nullptr, BLTOP_AND_NOT);
}
// Reenable the kernal rom
mmap_set(MMAP_ROM);
// Set name for file and open it with replace on drive 9
krnio_setnam("@0:TESTIMAGE,P,W");
if (krnio_open(2, 9, 2))
{
// Loop in chunks of 200 bytes
for(int i=0; i<8000; i+=200)
{
// Disable ROM
mmap_set(MMAP_NO_ROM);
// Copy chunk into buffer
memcpy(Buffer, ScreenMem + i, 200);
// Reeable the ROM
mmap_set(MMAP_ROM);
// Write the chunk to disk
krnio_write(2, Buffer, 200);
}
// Close the file
krnio_close(2);
}
// Restore the VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
call ..\..\bin\oscar64 diskdir.c
call ..\..\bin\oscar64 filewrite.c
call ..\..\bin\oscar64 fileread.c
call ..\..\bin\oscar64 charwrite.c
call ..\..\bin\oscar64 charread.c
call ..\..\bin\oscar64 hireswrite.c
call ..\..\bin\oscar64 hiresread.c
call ..\..\bin\oscar64 hiresfload.c -d64=hiresfload.d64 -fz=../resources/blumba2.bin
+8
View File
@@ -0,0 +1,8 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: diskdir.prg filewrite.prg fileread.prg charwrite.prg charread.prg hireswrite.prg hiresread.prg
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg *.bcs
+44
View File
@@ -0,0 +1,44 @@
cd fractals
call make.bat
cd ..
cd games
call make.bat
cd ..
cd hires
call make.bat
cd ..
cd hiresmc
call make.bat
cd ..
cd particles
call make.bat
cd ..
cd kernalio
call make.bat
cd ..
cd memmap
call make.bat
cd ..
cd rasterirq
call make.bat
cd ..
cd scrolling
call make.bat
cd ..
cd sprites
call make.bat
cd ..
cd stdio
call make.bat
cd ..
+25
View File
@@ -0,0 +1,25 @@
all:
@$(MAKE) -C fractals
@$(MAKE) -C games
@$(MAKE) -C hires
@$(MAKE) -C hiresmc
@$(MAKE) -C particles
@$(MAKE) -C kernalio
@$(MAKE) -C memmap
@$(MAKE) -C rasterirq
@$(MAKE) -C scrolling
@$(MAKE) -C sprites
@$(MAKE) -C stdio
clean:
@$(MAKE) -C fractals $@
@$(MAKE) -C games $@
@$(MAKE) -C hires $@
@$(MAKE) -C hiresmc $@
@$(MAKE) -C particles $@
@$(MAKE) -C kernalio $@
@$(MAKE) -C memmap $@
@$(MAKE) -C rasterirq $@
@$(MAKE) -C scrolling $@
@$(MAKE) -C sprites $@
@$(MAKE) -C stdio $@
+50
View File
@@ -0,0 +1,50 @@
#include <c64/memmap.h>
#include <stdlib.h>
#include <stdio.h>
// make space until 0x1000 by for the stack
#pragma stacksize(0x0600)
#pragma region( stack, 0x0a00, 0x1000, , , {stack} )
// everything beyond will be code, data, bss and heap to the end
#pragma region( main, 0x1000, 0xfff0, , , {code, data, bss, heap} )
int main(void)
{
// Install the IRQ trampoline
mmap_trampoline();
// Hide the basic ROM, must be first instruction
mmap_set(MMAP_RAM);
// Allocate all memory
unsigned total = 0;
while (char * data = malloc(1024))
{
total += 1024;
// Swap in kernal for print
mmap_set(MMAP_NO_BASIC);
printf("ALLOCATED %5u AT %04x\n", total, (unsigned)data);
mmap_set(MMAP_RAM);
// Fill it with trash
for(unsigned i=0; i<1024; i++)
data[i] = 0xaa;
}
// Return basic ROM to normal state
mmap_set(MMAP_ROM);
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
#!/bin/sh
../../bin/oscar64 largemem.c
../../bin/oscar64 allmem.c
../../bin/oscar64 charsetlo.c
../../bin/oscar64 charsethi.c
../../bin/oscar64 charsetcopy.c
../../bin/oscar64 charsetexpand.c
../../bin/oscar64 charsetload.c -d64=charsetload.d64 -fz=../resources/charset.bin
../../bin/oscar64 easyflash.c -n -tf=crt
../../bin/oscar64 easyflashreloc.c -n -tf=crt
../../bin/oscar64 easyflashshared.c -n -tf=crt
../../bin/oscar64 easyflashcall.cpp -n -tf=crt
../../bin/oscar64 tsr.c -n -dNOFLOAT -dNOLONG
../../bin/oscar64 overlay.c -n -d64=overlay.d64
+69
View File
@@ -0,0 +1,69 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// make space until 0xcc00 by extending the default region
#pragma region( main, 0x0a00, 0xcc00, , , {code, data, bss, heap, stack} )
// space for our custom charset from c000 to c800, will be copied to
// 0xd000 during startup to free space for stack and heap
#pragma section( charset, 0)
#pragma region( charset, 0xc000, 0xc800, , , {charset} )
// set initialized data segment to charset section
#pragma data(charset)
char charset[2048] = {
#embed "../resources/charset.bin"
};
// back to normal
#pragma data(data)
// pointers to charset and screen in memory
#define Screen ((char *)0xcc00)
#define Charset ((char *)0xd000)
int main(void)
{
// Install the trampoline
mmap_trampoline();
// make all of RAM visible to the CPU
mmap_set(MMAP_RAM);
// copy the font
memcpy(Charset, charset, 2048);
// make lower part of RAM visible to CPU
mmap_set(MMAP_NO_BASIC);
// map the vic to the new charset
vic_setmode(VICM_TEXT, Screen, Charset);
for(int i=0; i<1000; i++)
Screen[i] = (char)i;
// wait for keypress
getchar();
// restore VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
// restore basic ROM
mmap_set(MMAP_ROM);
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <oscar.h>
// make space until 0xcc00 by extending the default region
#pragma region( main, 0x0a00, 0xcc00, , , {code, data, bss, heap, stack} )
// space for our custom charset from c000 to c800, will be copied to
// 0xd000 during startup to free space for stack and heap
#pragma section( charset, 0)
#pragma region( charset, 0xc000, 0xc800, , , {charset} )
// set initialized data segment to charset section
#pragma data(charset)
// lz compressed data
char charset[] = {
#embed 2048 0 lzo "../resources/charset.bin"
};
// back to normal
#pragma data(data)
// pointers to charset and screen in memory
#define Screen ((char *)0xcc00)
#define Charset ((char *)0xd000)
int main(void)
{
// Install the trampoline
mmap_trampoline();
// make all of RAM visible to the CPU
mmap_set(MMAP_RAM);
// expand the font
oscar_expand_lzo(Charset, charset);
// make lower part of RAM visible to CPU
mmap_set(MMAP_NO_BASIC);
// map the vic to the new charset
vic_setmode(VICM_TEXT, Screen, Charset);
for(int i=0; i<1000; i++)
Screen[i] = (char)i;
// wait for keypress
getchar();
// restore VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
// restore basic ROM
mmap_set(MMAP_ROM);
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
#include <c64/vic.h>
#include <stdlib.h>
#include <stdio.h>
// space for our custom charset from c800
#pragma section( charset, 0)
#pragma region( charset, 0xc800, 0xd000, , , {charset} )
#pragma data(charset)
char charset[2048] = {
#embed "../resources/charset.bin"
};
#pragma data(data)
#define Screen ((char *)0xc000)
int main(void)
{
// map the vic to the new charset
vic_setmode(VICM_TEXT, Screen, charset);
for(int i=0; i<1000; i++)
Screen[i] = (char)i;
return 0;
}
+39
View File
@@ -0,0 +1,39 @@
#include <c64/vic.h>
#include <stdlib.h>
#include <stdio.h>
// make space until 0x2000 for code and data
#pragma region( lower, 0x0a00, 0x2000, , , {code, data} )
// then space for our custom charset
#pragma section( charset, 0)
#pragma region( charset, 0x2000, 0x2800, , , {charset} )
// everything beyond will be code, data, bss and heap to the end
#pragma region( main, 0x2800, 0xa000, , , {code, data, bss, heap, stack} )
#pragma data(charset)
char charset[2048] = {
#embed "../resources/charset.bin"
};
#pragma data(data)
int main(void)
{
// map the vic to the new charset
vic_setmode(VICM_TEXT, (char *)0x0400, charset);
for(int i=0; i<10; i++)
printf(p"%D Hello World\n", i);
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <c64/kernalio.h>
#include <stdio.h>
#define Screen ((char *)0xcc00)
#define Charset ((char *)0xc000)
int main(void)
{
// Set name for file and open it on drive 9
krnio_setnam("CHARSET,P,R");
if (krnio_open(2, 8, 2))
{
// Read the content of the file into the charset buffer,
// decompressing on the fly
krnio_read_lzo(2, Charset);
// Close the file
krnio_close(2);
}
// Change display address to new screen and charset
vic_setmode(VICM_TEXT, Screen, Charset);
for(int i=0; i<1000; i++)
Screen[i] = (char)i;
// wait for keypress
getchar();
// restore VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
// restore basic ROM
mmap_set(MMAP_ROM);
return 0;
}
+164
View File
@@ -0,0 +1,164 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/easyflash.h>
// Shared code/data region, copied from easyflash bank 0 to ram during startup
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
// Section and region for first easyflash bank
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xc000, , 1, { bcode1, bdata1 } )
// Section and region for second easyflash bank
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0xc000, , 2, { bcode2, bdata2 } )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0xc000, , 3, { bcode3, bdata3 } )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0xc000, , 4, { bcode4, bdata4 } )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0xc000, , 5, { bcode5, bdata5 } )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0xc000, , 6, { bcode6, bdata6 } )
// Charwin in shared memory section
CharWin cw;
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first bank", 7);
cwin_cursor_newline(&cw);
}
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2(void)
{
cwin_put_string(&cw, p"This is second bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3(void)
{
cwin_put_string(&cw, p"This is third bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4(void)
{
cwin_put_string(&cw, p"This is fourth bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5(void)
{
cwin_put_string(&cw, p"This is fifth bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6(void)
{
cwin_put_string(&cw, p"This is sixth bank", 7);
cwin_cursor_newline(&cw);
}
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
// Function for indirect cross bank call
void fcall(char bank, void (* func)())
{
eflash.bank = bank;
func();
}
// Macro for indirect cross bank call
#define FCALL(f) fcall(__bankof(f), f)
int main(void)
{
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
// Switch easyflash ROM region to bank 1
eflash.bank = 1;
// Call function in bank 1
print1();
// Switch easyflash ROM region to bank 2
eflash.bank = 2;
// Call function in bank 2
print2();
eflash.bank = 3;
print3();
// Get bank of function using __bankof operator
eflash.bank = __bankof print4;
print4();
// Indirect call
fcall(__bankof print5, print5);
// Macro call
FCALL(print6);
// Loop forever
while (true)
;
return 0;
}
+158
View File
@@ -0,0 +1,158 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/easyflash.h>
// Shared code/data region, copied from easyflash bank 0 to ram during startup
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
// Section and region for first easyflash bank
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xc000, , 1, { bcode1, bdata1 } )
// Section and region for second easyflash bank
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0xc000, , 2, { bcode2, bdata2 } )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0xc000, , 3, { bcode3, bdata3 } )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0xc000, , 4, { bcode4, bdata4 } )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0xc000, , 5, { bcode5, bdata5 } )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0xc000, , 6, { bcode6, bdata6 } )
// Charwin in shared memory section
CharWin cw;
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1_p(void)
{
cwin_put_string(&cw, p"This is first bank", 7);
cwin_cursor_newline(&cw);
}
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2_p(const char * p)
{
cwin_put_string(&cw, p"This is second bank:", 7);
cwin_put_string(&cw, p, 1);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3_p(void)
{
cwin_put_string(&cw, p"This is third bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4_p(int x, int y)
{
cwin_cursor_move(&cw, x, y);
cwin_put_string(&cw, p"This is fourth bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5_p(void)
{
cwin_put_string(&cw, p"This is fifth bank", 7);
cwin_cursor_newline(&cw);
}
void print5a_p(void)
{
cwin_put_string(&cw, p"This is fifth bank second", 14);
cwin_cursor_newline(&cw);
}
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
EF_CALL(print1);
EF_CALL(print2);
EF_CALL(print3);
EF_CALL(print4);
EF_CALL(print5);
EF_CALL(print5a);
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6_p(void)
{
cwin_put_string(&cw, p"This is sixth bank", 7);
cwin_cursor_newline(&cw);
print5a();
cwin_put_string(&cw, p"This is sixth bank again", 7);
}
#pragma code ( code )
#pragma data ( data )
EF_CALL(print6);
int main(void)
{
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
print1();
print2("hello");
print3();
print4(5, 8);
print5();
print6();
// Loop forever
while (true)
;
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <string.h>
#pragma section( startup, 0 )
#pragma region( startup, 0x0100, 0x0200, , , { startup } )
#pragma region( main, 0x0400, 0x8000, , , { code, data, bss, heap, stack } )
CharWin cw;
int main(void)
{
// Copy Char ROM
mmap_set(MMAP_ALL_ROM);
memcpy((char *)0xd000, (char *)0xd000, 0x1000);
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Init VIC
vic_setmode(VICM_TEXT, (char *)0xc000, (char *)0xd800);
// Prepare output window
cwin_init(&cw, (char *)0xc000, 0, 0, 40, 25);
cwin_clear(&cw);
cwin_put_string(&cw, p"Hello World", 7);
while (true) ;
}
+231
View File
@@ -0,0 +1,231 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/easyflash.h>
#include <string.h>
// Shared code/data region, copied from easyflash bank 0 to ram during startup
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
// Section and region for first easyflash bank, code is compiled for a
// target address of 0x7000 but placed into the bank at 0x8000
// The data section is first to ensure the jump table is at the start
// address
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0x9000, , 1, { bdata1, bcode1 }, 0x7000 )
// Section and region for second easyflash bank
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0x9000, , 2, { bdata2, bcode2 }, 0x7000 )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0x9000, , 3, { bdata3, bcode3 }, 0x7000 )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0x9000, , 4, { bdata4, bcode4 }, 0x7000 )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0x9000, , 5, { bdata5, bcode5 }, 0x7000 )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0x9000, , 6, { bdata6, bcode6 } , 0x7000 )
// Charwin in shared memory section
CharWin cw;
struct EntryTable
{
void (*fhello)(void);
void (*fdone)(void);
};
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first bank", 7);
}
void done1(void)
{
cwin_cursor_newline(&cw);
}
const EntryTable entry1 = {
.fhello = &print1,
.fdone = &done1
};
// make sure the function is referenced
#pragma reference(entry1)
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2(void)
{
cwin_put_string(&cw, p"This is second bank", 7);
}
void done2(void)
{
cwin_cursor_newline(&cw);
}
const EntryTable entry2 = {
.fhello = &print2,
.fdone = &done2
};
// make sure the function is referenced
#pragma reference(entry2)
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3(void)
{
cwin_put_string(&cw, p"This is third bank", 7);
}
void done3(void)
{
cwin_cursor_newline(&cw);
}
const EntryTable entry3 = {
.fhello = &print3,
.fdone = &done3
};
#pragma reference(entry3)
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4(void)
{
cwin_put_string(&cw, p"This is fourth bank", 7);
}
void done4(void)
{
cwin_cursor_newline(&cw);
}
const EntryTable entry4 = {
.fhello = &print4,
.fdone = &done4
};
#pragma reference(entry4)
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5(void)
{
cwin_put_string(&cw, p"This is fifth bank", 7);
}
void done5(void)
{
cwin_cursor_newline(&cw);
}
const EntryTable entry5 = {
.fhello = &print5,
.fdone = &done5
};
#pragma reference(entry5)
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6(void)
{
cwin_put_string(&cw, p"This is sixth bank", 7);
}
void done6(void)
{
cwin_cursor_newline(&cw);
}
const EntryTable entry6 = {
.fhello = &print6,
.fdone = &done6
};
#pragma reference(entry6)
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
// Copy the data of the rom bank, and call the function
// with the jump table
void callbank(char bank)
{
eflash.bank = bank;
memcpy((char *)0x7000, (char *)0x8000, 0x1000);
// call function at start of copied section
((EntryTable *)0x7000)->fhello();
((EntryTable *)0x7000)->fdone();
}
int main(void)
{
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
// Call function in bank 1
callbank(1);
// Switch easyflash ROM region to bank 2
callbank(2);
callbank(3);
callbank(4);
callbank(5);
callbank(6);
// Loop forever
while (true)
;
return 0;
}
+158
View File
@@ -0,0 +1,158 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/easyflash.h>
// Shared code/data region, copied from easyflash bank 0 to ram during startup
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xbf00, , 1, { bcode1, bdata1 } )
// Section and region for second easyflash bank
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0xbf00, , 2, { bcode2, bdata2 } )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0xbf00, , 3, { bcode3, bdata3 } )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0xbf00, , 4, { bcode4, bdata4 } )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0xbf00, , 5, { bcode5, bdata5 } )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0xbf00, , 6, { bcode6, bdata6 } )
// Charwin in shared memory section
CharWin cw;
// Setting up a common range
#pragma section( ccode, 0 )
#pragma region( cbank, 0xbf00, 0xc000, , {1, 2, 3, 4, 5, 6}, { ccode } )
// Code shared by all banks
#pragma code( ccode )
__export void callbank(void (* fn)(void), char bank)
{
eflash.bank = bank;
fn();
}
#pragma code( code )
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first bank", 7);
cwin_cursor_newline(&cw);
}
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2(void)
{
cwin_put_string(&cw, p"This is second bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3(void)
{
cwin_put_string(&cw, p"This is third bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4(void)
{
cwin_put_string(&cw, p"This is fourth bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5(void)
{
cwin_put_string(&cw, p"This is fifth bank", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6(void)
{
cwin_put_string(&cw, p"This is sixth bank", 7);
cwin_cursor_newline(&cw);
}
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
int main(void)
{
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
eflash.bank = 1;
// Call function in bank 1
callbank(print1, 1);
// Call function in bank 2
callbank(print2, 2);
callbank(print3, 3);
callbank(print4, 4);
callbank(print5, 5);
callbank(print6, 6);
// Loop forever
while (true)
;
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
#include <c64/memmap.h>
#include <stdlib.h>
#include <stdio.h>
// make space until 0xd000 by extending the default region
#pragma region( main, 0x0a00, 0xd000, , , {code, data, bss, heap, stack} )
int main(void)
{
// Hide the basic ROM, must be first instruction
mmap_set(MMAP_NO_BASIC);
// Allocate all memory
unsigned total = 0;
while (char * data = malloc(1024))
{
total += 1024;
printf("ALLOCATED %5u AT %04x\n", total, (unsigned)data);
// Fill it with trash
for(unsigned i=0; i<1024; i++)
data[i] = 0xaa;
}
// Return basic ROM to normal state
mmap_set(MMAP_ROM);
return 0;
}
+95
View File
@@ -0,0 +1,95 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
// Set rom region end at 0x9f80 to leave some space for copy code
#pragma region(rom, 0x8080, 0x9f80, , 0, { code, data } )
// We do not want to pollute main RAM region with our data
#pragma region(main, 0xc000, 0xd000, , , { bss, stack, heap })
#pragma stacksize( 256 )
// Region and code for a cross bank copy routine
#pragma section( ccode, 0 )
#pragma region( crom, 0x9f80, 0xa000, , 0, { ccode }, 0x0380 )
CharWin cw;
// Copy code from any bank to RAM, returns to bank 0, this code is
// copied from bank 0 to RAM at 0x0380 at program start
#pragma code ( ccode )
__export void ccopy(char bank, char * dst, const char * src, unsigned n)
{
*((volatile char *)0xde00) = bank;
while (n)
{
*dst++ = *src++;
n--;
}
*((volatile char *)0xde00) = 0;
}
// Region of code to be executed from RAM after copied from 2nd ROM
// bank
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xa000, , 1, { bcode1, bdata1 }, 0x2000 )
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first bank", 1);
cwin_cursor_newline(&cw);
}
// Back to main sections in bank 0
#pragma code ( code )
#pragma data ( data )
int main(void)
{
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Copy ccopy code to RAM
for(char i=0; i<128; i++)
((char *)0x0380)[i] = ((char *)0x9f80)[i];
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
// Write first line
cwin_put_string(&cw, p"Hello World", 7);
cwin_cursor_newline(&cw);
// Copy bank 1 to RAM
ccopy(1, (char *)0x2000, (char *)0x8000, 0x2000);
// Call function in copy
print1();
// Third line
cwin_put_string(&cw, p"Final words", 14);
cwin_cursor_newline(&cw);
while (true) ;
return 0;
}
+16
View File
@@ -0,0 +1,16 @@
call ..\..\bin\oscar64 largemem.c
call ..\..\bin\oscar64 allmem.c
call ..\..\bin\oscar64 charsetlo.c
call ..\..\bin\oscar64 charsethi.c
call ..\..\bin\oscar64 charsetcopy.c
call ..\..\bin\oscar64 charsetexpand.c
call ..\..\bin\oscar64 charsetload.c -d64=charsetload.d64 -fz=../resources/charset.bin
call ..\..\bin\oscar64 easyflash.c -n -tf=crt
call ..\..\bin\oscar64 easyflashreloc.c -n -tf=crt
call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt
call ..\..\bin\oscar64 easyflashlow.c -n -tf=crt
call ..\..\bin\oscar64 easyflashcall.cpp -n -tf=crt
call ..\..\bin\oscar64 tsr.c -n -dNOFLOAT -dNOLONG
call ..\..\bin\oscar64 overlay.c -n -d64=overlay.d64
call ..\..\bin\oscar64 overlaylzo.c -n -d64=overlaylzo.d64
call ..\..\bin\oscar64 magicdesk.c -n -tf=crt8 -cid=19
+30
View File
@@ -0,0 +1,30 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: largemem.prg allmem.prg charsetlo.prg charsethi.prg charsetcopy.prg charsetexpand.prg \
charsetload.prg easyflash.crt easyflashreloc.crt easyflashshared.crt tsr.prg overlay.prg
charsetload.prg: charsetload.c ../resources/charset.bin
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -d64=charsetload.d64 -fz=../resources/charset.bin
easyflash.crt: easyflash.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n -tf=crt
easyflashreloc.crt: easyflashreloc.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n -tf=crt
easyflashshared.crt: easyflashshared.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n -tf=crt
tsr.prg: tsr.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n -dNOFLOAT -dNOLONG
overlay.prg: overlay.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n -d64=overlay.d64
overlay.prg: overlaylzo.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n -d64=overlaylzo.d64
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg *.bcs *.d64 *.crt
+157
View File
@@ -0,0 +1,157 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/kernalio.h>
// Common memory area for all overlays
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
// Section and region for first overlay bank
#pragma overlay( ovl1, 1 )
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xc000, , 1, { bcode1, bdata1 } )
// Section and region for second overlay bank
#pragma overlay( ovl2, 2 )
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0xc000, , 2, { bcode2, bdata2 } )
#pragma overlay( ovl3, 3 )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0xc000, , 3, { bcode3, bdata3 } )
#pragma overlay( ovl4, 4 )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0xc000, , 4, { bcode4, bdata4 } )
#pragma overlay( ovl5, 5 )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0xc000, , 5, { bcode5, bdata5 } )
#pragma overlay( ovl6, 6 )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0xc000, , 6, { bcode6, bdata6 } )
// Charwin in shared memory section
CharWin cw;
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first overlay", 7);
cwin_cursor_newline(&cw);
}
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2(void)
{
cwin_put_string(&cw, p"This is second overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3(void)
{
cwin_put_string(&cw, p"This is third overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4(void)
{
cwin_put_string(&cw, p"This is fourth overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5(void)
{
cwin_put_string(&cw, p"This is fifth overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6(void)
{
cwin_put_string(&cw, p"This is sixth overlay", 7);
cwin_cursor_newline(&cw);
}
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
// Load an overlay section into memory
void load(const char * fname)
{
krnio_setnam(fname);
krnio_load(1, 8, 1);
}
int main(void)
{
// Kernal memory only
mmap_set(MMAP_NO_BASIC);
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
// Call function in overlay 1
load(P"OVL1");
print1();
// Call function in overlay 2
load(P"OVL2");
print2();
load(P"OVL3");
print3();
load(P"OVL4");
print4();
load(P"OVL5");
print5();
load(P"OVL6");
print6();
mmap_set(MMAP_ROM);
return 0;
}
+170
View File
@@ -0,0 +1,170 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <c64/kernalio.h>
#include <oscar.h>
// Common memory area for all overlays
#pragma region( main, 0x0900, 0x8000, , , { code, data, bss, heap, stack } )
// Section and region for first overlay bank
#pragma overlay( ovl1, 1, lzo )
#pragma section( bcode1, 0 )
#pragma section( bdata1, 0 )
#pragma region(bank1, 0x8000, 0xc000, , 1, { bcode1, bdata1 } )
// Section and region for second overlay bank
#pragma overlay( ovl2, 2, lzo )
#pragma section( bcode2, 0 )
#pragma section( bdata2, 0 )
#pragma region(bank2, 0x8000, 0xc000, , 2, { bcode2, bdata2 } )
#pragma overlay( ovl3, 3, lzo )
#pragma section( bcode3, 0 )
#pragma section( bdata3, 0 )
#pragma region(bank3, 0x8000, 0xc000, , 3, { bcode3, bdata3 } )
#pragma overlay( ovl4, 4, lzo )
#pragma section( bcode4, 0 )
#pragma section( bdata4, 0 )
#pragma region(bank4, 0x8000, 0xc000, , 4, { bcode4, bdata4 } )
#pragma overlay( ovl5, 5, lzo )
#pragma section( bcode5, 0 )
#pragma section( bdata5, 0 )
#pragma region(bank5, 0x8000, 0xc000, , 5, { bcode5, bdata5 } )
#pragma overlay( ovl6, 6, lzo )
#pragma section( bcode6, 0 )
#pragma section( bdata6, 0 )
#pragma region(bank6, 0x8000, 0xc000, , 6, { bcode6, bdata6 } )
// Charwin in shared memory section
CharWin cw;
// Now switch code generation to bank 1
#pragma code ( bcode1 )
#pragma data ( bdata1 )
// Print into shared charwin
void print1(void)
{
cwin_put_string(&cw, p"This is first overlay", 7);
cwin_cursor_newline(&cw);
}
// Now switch code generation to bank 2
#pragma code ( bcode2 )
#pragma data ( bdata2 )
void print2(void)
{
cwin_put_string(&cw, p"This is second overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode3 )
#pragma data ( bdata3 )
void print3(void)
{
cwin_put_string(&cw, p"This is third overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode4 )
#pragma data ( bdata4 )
void print4(void)
{
cwin_put_string(&cw, p"This is fourth overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode5 )
#pragma data ( bdata5 )
void print5(void)
{
cwin_put_string(&cw, p"This is fifth overlay", 7);
cwin_cursor_newline(&cw);
}
#pragma code ( bcode6 )
#pragma data ( bdata6 )
void print6(void)
{
cwin_put_string(&cw, p"This is sixth overlay", 7);
cwin_cursor_newline(&cw);
}
// Switching code generation back to shared section
#pragma code ( code )
#pragma data ( data )
// Load an overlay section into memory
void load(const char * fname)
{
krnio_setnam(fname);
if (krnio_open(2, 8, 2))
{
if (krnio_chkin(2))
{
char lo = krnio_chrin();
char hi = krnio_chrin();
char * dp = (char *)((hi << 8) | lo);
krnio_clrchn();
krnio_read_lzo(2, dp);
}
krnio_close(2);
}
}
int main(void)
{
// Kernal memory only
mmap_set(MMAP_NO_BASIC);
// Init VIC
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1800);
// Prepare output window
cwin_init(&cw, (char *)0x0400, 0, 0, 40, 25);
cwin_clear(&cw);
// Call function in overlay 1
load(P"OVL1");
print1();
// Call function in overlay 2
load(P"OVL2");
print2();
load(P"OVL3");
print3();
load(P"OVL4");
print4();
load(P"OVL5");
print5();
load(P"OVL6");
print6();
mmap_set(MMAP_ROM);
return 0;
}
+70
View File
@@ -0,0 +1,70 @@
#include <string.h>
#include <stdio.h>
#include <c64/asm6502.h>
// Invoke resident section with "SYS 49152" from basic
// not much space, so we go with a smaller stack size
#pragma stacksize(256)
// shrink size of startup section
#pragma section(startup, 0);
#pragma region(startup, 0x0801, 0x0870, , , { startup } )
// section for code copy
#pragma section(rcode, 0)
#pragma region(rcode, 0x0870, 0x0900, , , { rcode } )
// main section to stay resident, save three bytes at the
// beginning to have space for an entry jump
#pragma region(main, 0x0903, 0x1900, , , {code, data, bss, heap, stack}, 0xc003 )
// resident entry routine
void tsr(void)
{
// Initialize stack pointer
__asm {
lda #$ff
sta __sp
lda #$cf
sta __sp +1
}
// do something useless
printf(p"Hello World\n");
// and done
}
// Now the copy code section
#pragma code(rcode)
int main(void)
{
// source and target address to copy, no memcpy as it is itself
// not yet copied
char * dp = (char *)0xc000;
char * sp = (char *)0x0903;
// A jmp to the code at the absolute address 0xc000 / 49152
dp += asm_ab(dp, ASM_JMP, (unsigned)tsr);
// then the code
for(unsigned i=0; i<0xffd; i++)
*dp++ = *sp++;
// now we are done
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
../../bin/oscar64 -n fireworks_ptr.c
../../bin/oscar64 -n fireworks_hires.c
../../bin/oscar64 -n fireworks_stripe.c
+215
View File
@@ -0,0 +1,215 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <string.h>
#include <stdlib.h>
static char * const Screen = (char *)0xc800;
static char * const Color = (char *)0xd800;
static char * const Hires = (char *)0xe000;
// Single particle, with position and veloicty, using a next
// pointer for single linked list
struct Particle
{
int px, py, vx, vy;
Particle * next;
};
// Storage for up to 256 particles
Particle particles[256];
// Heads of used and free list
Particle * pfirst, * pfree;
// Lookup table for hires row buffer
static char * Hirows[25];
// Pixel masks
static const char setmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
static const char clrmask[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe};
// Set a pixel at the given coordinate
void pix_set(unsigned px, unsigned py)
{
// Give the compiler a hand
__assume(px < 320);
__assume(py < 200);
// Calculate base position in hires
char * dp = Hirows[py >> 3] + (px & ~7);
// Set the pixel
dp[py & 7] |= setmask[px & 7];
}
// Clear a pixel at the given coordinate
void pix_clr(unsigned px, unsigned py)
{
__assume(px < 320);
__assume(py < 200);
// Calculate base position in hires
char * dp = Hirows[py >> 3] + (px & ~7);
// Clear the pixel
dp[py & 7] &= clrmask[px & 7];
}
// Init free list of particles
void particle_init(void)
{
// Init address table for hires
for(int i=0; i<25; i++)
Hirows[i] = Hires + 320 * i;
// Init list heads
pfirst = nullptr;
pfree = particles;
// Link all particles in free list
for(int i=0; i<255; i++)
particles[i].next = particles + i + 1;
}
// Add a particle to the list
void particle_add(int px, int py, int vx, int vy)
{
// Check if we have a particle left
if (pfree)
{
// Remove from free list
Particle * p = pfree;
pfree = pfree->next;
// Add to used list
p->next = pfirst;
pfirst = p;
// Init particle data
p->px = px;
p->py = py;
p->vx = vx;
p->vy = vy;
}
}
// Move particles in used list
void particle_move(void)
{
// Start with first particle, remember previous
// particle for list removal
Particle * p = pfirst, * pp = nullptr;
// Loop over all particles in used list
while (p)
{
// Clear previous particle image, using 10.6 fixed point
pix_clr(p->px >> 6, p->py >> 6);
// Advance position by velocity
p->px += p->vx;
p->py += p->vy;
// Apply gravity
p->vy += 8;
// Check if particle is still on screen
if (p->px < 0 || p->px >= 320 * 64 || p->py < 0 || p->py >= 200 * 64)
{
// Particle is offscreen, so we remove it from the used list
// Remember next particle in used list
Particle * pn = p->next;
// Remove from used list
if (pp)
pp->next = pn;
else
pfirst = pn;
// Attach to free list
p->next = pfree;
pfree = p;
// Advance to next particle
p = pn;
}
else
{
// Set image at new position
pix_set(p->px >> 6, p->py >> 6);
// Advance to next particle
pp = p;
p = p->next;
}
}
}
// Normalized random function
int rnorm(void)
{
int l0 = (rand() & 0xfff) - 0x800;
int l1 = (rand() & 0xfff) - 0x800;
int l2 = (rand() & 0xfff) - 0x800;
int l3 = (rand() & 0xfff) - 0x800;
return l0 + l1 + l2 + l3;
}
int main(void)
{
// Turn off BASIC ROM
mmap_set(MMAP_NO_BASIC);
// Install IRQ trampoline
mmap_trampoline();
// Turn off kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch to hires mode
vic_setmode(VICM_HIRES, Screen, Hires);
// Clear screen
memset(Screen, 0x10, 1000);
memset(Hires, 0x00, 8000);
// Black background
vic.color_border = 0x00;
vic.color_back = 0x00;
// Init particle system
particle_init();
char k = 0;
for(int i=0; i<10000; i++)
{
// Advance particles
particle_move();
if (k < 25)
{
// Add a particle from the left for the first third
particle_add(4 * 64, 196 * 64, 256 + (rnorm() >> 6), -(384 + (rnorm() >> 6)));
}
else if (k < 50)
{
// Add a particle from the right for the second third
particle_add(316 * 64, 196 * 64, - (256 + (rnorm() >> 6)), -(384 + (rnorm() >> 6)));
}
else if (k < 75)
{
// Add a particle from the middle for the final third
particle_add(160 * 64, 196 * 64, rnorm() >> 6, -(384 + (rnorm() >> 6)));
}
// Advance thirds counter
k++;
if (k == 75)
k = 0;
}
return 0;
}
+219
View File
@@ -0,0 +1,219 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <string.h>
#include <stdlib.h>
static char * const Screen = (char *)0xc800;
static char * const Color = (char *)0xd800;
static char * const Hires = (char *)0xe000;
// Single particle, with position, veloicty and color pattern, using a next
// pointer for single linked list
struct Particle
{
int px, py, vx, vy;
char pat;
Particle * next;
};
// Storage for up to 256 particles
Particle particles[256];
// Heads of used and free list
Particle * pfirst, * pfree;
// Lookup table for hires row buffer
static char * Hirows[25];
// Pixel masks
static const char setmask[8] = {0xc0, 0xc0, 0x30, 0x30, 0x0c, 0x0c, 0x03, 0x03};
static const char clrmask[8] = {0x3f, 0x3f, 0xcf, 0xcf, 0xf3, 0xf3, 0xfc, 0xfc};
// Set a pixel at the given coordinate
void pix_set(unsigned px, unsigned py, char pat)
{
__assume(px < 320);
__assume(py < 200);
// Calculate base position in hires
char * dp = Hirows[py >> 3] + (px & ~7);
// Set two pixels for a square pixel look
char ly = py & 6;
dp[ly + 1] = dp[ly + 0] |= setmask[px & 7] & pat;
}
// Clear a pixel at the given coordinate
void pix_clr(unsigned px, unsigned py)
{
__assume(px < 320);
__assume(py < 200);
// Calculate base position in hires
char * dp = Hirows[py >> 3] + (px & ~7);
// Clear two pixels for a square pixel look
char ly = py & 6;
dp[ly + 1] = dp[ly + 0] &= clrmask[px & 7];
}
// Init free list of particles
void particle_init(void)
{
// Init address table for hires
for(int i=0; i<25; i++)
Hirows[i] = Hires + 320 * i;
// Init list heads
pfirst = nullptr;
pfree = particles;
// Link all particles in free list
for(int i=0; i<255; i++)
particles[i].next = particles + i + 1;
}
// Add a particle to the list
void particle_add(int px, int py, int vx, int vy, char pat)
{
// Check if we have a particle left
if (pfree)
{
// Remove from free list
Particle * p = pfree;
pfree = pfree->next;
// Add to used list
p->next = pfirst;
pfirst = p;
// Init particle data
p->px = px;
p->py = py;
p->vx = vx;
p->vy = vy;
p->pat = pat;
}
}
// Move particles in used list
void particle_move(void)
{
// Start with first particle, remember previous
// particle for list removal
Particle * p = pfirst, * pp = nullptr;
// Loop over all particles in used list
while (p)
{
// Clear previous particle image, using 10.6 fixed point
pix_clr(p->px >> 6, p->py >> 6);
// Advance position by velocity
p->px += p->vx;
p->py += p->vy;
// Apply gravity
p->vy += 8;
// Check if particle is still on screen
if (p->px < 0 || p->px >= 320 * 64 || p->py < 0 || p->py >= 200 * 64)
{
// Particle is offscreen, so we remove it from the used list
// Remember next particle in used list
Particle * pn = p->next;
// Remove from used list
if (pp)
pp->next = pn;
else
pfirst = pn;
// Attach to free list
p->next = pfree;
pfree = p;
// Advance to next particle
p = pn;
}
else
{
// Set image at new position
pix_set(p->px >> 6, p->py >> 6, p->pat);
// Advance to next particle
pp = p;
p = p->next;
}
}
}
// Normalized random function
int rnorm(void)
{
int l0 = (rand() & 0xfff) - 0x800;
int l1 = (rand() & 0xfff) - 0x800;
int l2 = (rand() & 0xfff) - 0x800;
int l3 = (rand() & 0xfff) - 0x800;
return l0 + l1 + l2 + l3;
}
int main(void)
{
// Turn off BASIC ROM
mmap_set(MMAP_NO_BASIC);
// Install IRQ trampoline
mmap_trampoline();
// Turn off kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch to hires multicolor mode
vic_setmode(VICM_HIRES_MC, Screen, Hires);
// Clear screen
memset(Screen, 0x78, 1000);
memset(Color, 0x0e, 1000);
memset(Hires, 0x00, 8000);
// Black background
vic.color_border = 0x00;
vic.color_back = 0x00;
// Init particle system
particle_init();
char k = 0;
for(int i=0; i<10000; i++)
{
// Advance particles
particle_move();
if (k < 25)
{
// Add a particle from the left for the first third
particle_add(4 * 64, 196 * 64, 256 + (rnorm() >> 6), -(384 + (rnorm() >> 6)), 0x55);
}
else if (k < 50)
{
// Add a particle from the right for the second third
particle_add(316 * 64, 196 * 64, - (256 + (rnorm() >> 6)), -(384 + (rnorm() >> 6)), 0xaa);
}
else if (k < 75)
{
// Add a particle from the middle for the final third
particle_add(160 * 64, 196 * 64, rnorm() >> 6, -(384 + (rnorm() >> 6)), 0xff);
}
// Advance thirds counter
k++;
if (k == 75)
k = 0;
}
return 0;
}
@@ -0,0 +1,226 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <string.h>
#include <stdlib.h>
static char * const Screen = (char *)0xc800;
static char * const Color = (char *)0xd800;
static char * const Hires = (char *)0xe000;
// Single particle, with position, veloicty and color pattern, using a next
// index for single linked list
struct Particle
{
int px, py, vx, vy;
char pat;
char next;
};
// Striped storage of particles, using an index for linkage
__striped Particle particles[256];
#pragma align(particles, 256)
// Index for used and free list heads
char pfirst, pfree;
static char * Hirows[25];
static const char setmask[4] = {0xc0, 0x30, 0x0c, 0x03};
static const char clrmask[4] = {0x3f, 0xcf, 0xf3, 0xfc};
// Set a pixel at the given coordinate
void pix_set(char px, char py, char pat)
{
__assume(px < 160);
__assume(py < 100);
// Calculate base position in hires
char * dp = Hirows[py >> 2] + 2 * (px & ~3);
// Set two pixels for a square pixel look
char ly = 2 * (py & 3);
dp[ly + 1] = dp[ly + 0] |= setmask[px & 3] & pat;
}
// Clear a pixel at the given coordinate
void pix_clr(char px, char py)
{
__assume(px < 160);
__assume(py < 100);
// Calculate base position in hires
char * dp = Hirows[py >> 2] + 2 * (px & ~3);
// Clear two pixels for a square pixel look
char ly = 2 * (py & 3);
dp[ly + 1] = dp[ly + 0] &= clrmask[px & 3];
}
// Init free list of particles
void particle_init(void)
{
// Init address table for hires
for(int i=0; i<25; i++)
Hirows[i] = Hires + 320 * i;
// Init list heads, using index 0 for list termination
pfirst = 0;
pfree = 1;
// Link all particles in free list
for(int i=1; i<255; i++)
particles[i].next = i + 1;
}
// Add a particle to the list
void particle_add(int px, int py, int vx, int vy, char pat)
{
// Check if we have a particle left
if (pfree)
{
// Use "auto" to generate a striped pointer
char i = pfree;
auto p = particles + pfree;
// Remove from free list
pfree = p->next;
p->next = pfirst;
// Add to used list
pfirst = i;
// Init particle data
p->px = px;
p->py = py;
p->vx = vx;
p->vy = vy;
p->pat = pat;
}
}
// Move particles in used list
void particle_move(void)
{
// Start with first particle, remember previous
// particle for list removal, using indices instead of pointers
char i = pfirst, pi = 0;
// Zero is still list termination
while (i)
{
// Use "auto" to generate a striped pointer
auto p = particles + i;
// Clear previous particle image, using 9.7 fixed point
pix_clr(p->px >> 7, p->py >> 7);
// Advance position by velocity
p->px += p->vx;
p->py += p->vy;
// Apply gravity
p->vy += 8;
// Check if particle is still on screen
if (p->px < 0 || p->px >= 160 * 128 || p->py < 0 || p->py >= 100 * 128)
{
// Particle is offscreen, so we remove it from the used list
// Remember next particle in used list
char pn = p->next;
// Remove from used list
if (pi)
particles[pi].next = pn;
else
pfirst = pn;
// Attach to free list
p->next = pfree;
pfree = i;
// Advance to next particle
i = pn;
}
else
{
// Set image at new position
pix_set(p->px >> 7, p->py >> 7, p->pat);
// Advance to next particle
pi = i;
i = p->next;
}
}
}
// Normalized random function
int rnorm(void)
{
int l0 = (rand() & 0xfff) - 0x800;
int l1 = (rand() & 0xfff) - 0x800;
int l2 = (rand() & 0xfff) - 0x800;
int l3 = (rand() & 0xfff) - 0x800;
return l0 + l1 + l2 + l3;
}
int main(void)
{
// Turn off BASIC ROM
mmap_set(MMAP_NO_BASIC);
// Install IRQ trampoline
mmap_trampoline();
// Turn off kernal ROM
mmap_set(MMAP_NO_ROM);
// Switch to hires multicolor mode
vic_setmode(VICM_HIRES_MC, Screen, Hires);
// Clear screen
memset(Screen, 0x78, 1000);
memset(Color, 0x0e, 1000);
memset(Hires, 0x00, 8000);
// Black background
vic.color_border = 0x00;
vic.color_back = 0x00;
// Init particle system
particle_init();
char k = 0;
for(int i=0; i<10000; i++)
{
// Advance particles
particle_move();
if (k < 25)
{
// Add a particle from the left for the first third
particle_add(4 * 64, 196 * 64, 256 + (rnorm() >> 6), -(384 + (rnorm() >> 6)), 0x55);
}
else if (k < 50)
{
// Add a particle from the right for the second third
particle_add(316 * 64, 196 * 64, - (256 + (rnorm() >> 6)), -(384 + (rnorm() >> 6)), 0xaa);
}
else if (k < 75)
{
// Add a particle from the middle for the final third
particle_add(160 * 64, 196 * 64, rnorm() >> 6, -(384 + (rnorm() >> 6)), 0xff);
}
// Advance thirds counter
k++;
if (k == 75)
k = 0;
}
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
call ..\..\bin\oscar64 -n fireworks_ptr.c
call ..\..\bin\oscar64 -n fireworks_hires.c
call ..\..\bin\oscar64 -n fireworks_stripe.c -O2
+8
View File
@@ -0,0 +1,8 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: fireworks_ptr.prg fireworks_hires.prg fireworks_stripe.prg
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg
+64
View File
@@ -0,0 +1,64 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <string.h>
const char Text[] =
S"LABORUM RERUM QUO. QUASI IN, SEQUI, TENETUR VOLUPTATEM RERUM "
S"PORRO NON ET MAIORES ALIAS ODIO EST EOS. MAGNAM APERIAM CUM ET "
S"ESSE TEMPORE ITAQUE TEMPORA VOLUPTAS ET IPSAM IPSAM EARUM. ID "
S"SUSCIPIT QUIA RERUM REPREHENDERIT ERROR ET UT. DOLOR ID "
S"CORPORIS, EOS? UNDE VERO ISTE QUIA? EAQUE EAQUE. IN. AUT ID "
S"EXPEDITA ILLUM MOLESTIAS, ";
// Raster interrupt command structure for change to scrolled and back
RIRQCode scroll, restore;
int x;
// Loop through text
__interrupt void doscroll(void)
{
vic.color_border++;
// Update raster IRQ for scroll line with new horizontal scroll offset
rirq_data(&scroll, 1, 7 - (x & 7));
// Copy scrolled version of text when switching over char border
if ((x & 7) == 0)
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
x++;
vic.color_border--;
}
int main(void)
{
// initialize raster IRQ
rirq_init(true);
// Build switch to scroll line IRQ
rirq_build(&scroll, 2);
// Delay for one line to get to right border
rirq_delay(&scroll, 11);
// Change control register two with this IRQ
rirq_write(&scroll, 1, &vic.ctrl2, 0);
// Put it onto the scroll line
rirq_set(0, 49 + 24 * 8, &scroll);
// Build the switch to normal IRQ
rirq_build(&restore, 2);
// re-enable left and right column and reset horizontal scroll
rirq_write(&restore, 0, &vic.ctrl2, VIC_CTRL2_CSEL);
// call scroll copy code
rirq_call(&restore, 1, doscroll);
// place this at the top of the screen before the display starts
rirq_set(1, 250, &restore);
// sort the raster IRQs
rirq_sort();
// start raster IRQ processing
rirq_start();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
../../bin/oscar64 colorbars.c
../../bin/oscar64 openborder.c
../../bin/oscar64 textcrawler.c
../../bin/oscar64 movingbars.c -n
+32
View File
@@ -0,0 +1,32 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <conio.h>
// Prepare small 14 color bars and one IRQ for back to normal
RIRQCode bars[15];
int main(void)
{
// initialize raster IRQ
rirq_init(true);
for(int i=0; i<15; i++)
{
// Build color change raster IRQ
rirq_build(bars + i, 2);
// Change border color
rirq_write(bars + i, 0, &vic.color_border, i);
// Change background color
rirq_write(bars + i, 1, &vic.color_back, i);
// Place it on screen
rirq_set(i, 80 + 8 * i, bars + i);
}
// Sort all raster IRQs
rirq_sort();
// Start raster IRQs
rirq_start();
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

+5
View File
@@ -0,0 +1,5 @@
call ..\..\bin\oscar64 colorbars.c
call ..\..\bin\oscar64 openborder.c
call ..\..\bin\oscar64 textcrawler.c
call ..\..\bin\oscar64 movingbars.c -n
call ..\..\bin\oscar64 autocrawler.c -n
+11
View File
@@ -0,0 +1,11 @@
%.prg: %.c
@echo "Compiling sample file" $<
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $<
all: colorbars.prg openborder.prg textcrawler.prg movingbars.prg
movingbars.prg: movingbars.c
@$(OSCAR64_CC) $(OSCAR64_CFLAGS) $< -n
clean:
@$(RM) *.asm *.int *.lbl *.map *.prg *.bcs
+94
View File
@@ -0,0 +1,94 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <string.h>
#include <math.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 ;
char sintab[256];
int main(void)
{
rirq_init(true);
rirq_build(&ftop, 3);
rirq_delay(&ftop, 10);
rirq_write(&ftop, 1, &vic.color_back, 2);
rirq_write(&ftop, 2, &vic.color_border, 2);
rirq_build(&fbottom, 3);
rirq_delay(&fbottom, 10);
rirq_write(&fbottom, 1, &vic.color_back, 6);
rirq_write(&fbottom, 2, &vic.color_border, 14);
rirq_build(&btop, 3);
rirq_delay(&btop, 10);
rirq_write(&btop, 1, &vic.color_back, 7);
rirq_write(&btop, 2, &vic.color_border, 7);
rirq_build(&bbottom, 3);
rirq_delay(&bbottom, 10);
rirq_write(&bbottom, 1, &vic.color_back, 6);
rirq_write(&bbottom, 2, &vic.color_border, 14);
rirq_build(&final, 0);
char yfront = 100, yback = 200;
rirq_set(0, yfront, &ftop);
rirq_set(1, yfront + 16, &fbottom);
rirq_set(2, yback, &btop);
rirq_set(3, yback + 16, &bbottom);
rirq_set(4, 250, &final);
rirq_sort();
rirq_start();
for(int i=0; i<32; i++)
sintab[i] = (int)(120 + 60 * sin(i * PI / 16)) | 1;
char fi = 3, bi = 0;
for(;;)
{
yfront = sintab[fi & 31];
yback = sintab[bi & 31];
rirq_move(0, yfront);
if (yback == yfront)
{
rirq_move(1, yfront + 16);
rirq_clear(2);
rirq_clear(3);
}
else
{
if (yback < yfront || yback > yfront + 16)
{
rirq_move(1, yfront + 16);
rirq_move(2, yback);
}
else
{
rirq_clear(1);
rirq_move(2, yfront + 16);
}
if (yback < yfront - 16 || yback > yfront)
rirq_move(3, yback + 16);
else
rirq_clear(3);
}
rirq_sort();
rirq_wait();
fi ++;
bi ++;
}
return 0;
}
+78
View File
@@ -0,0 +1,78 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <conio.h>
#include <string.h>
char spdata[] = {
#embed "../resources/friendlybear.bin"
};
// Raster IRQs for last line of screen and below
RIRQCode open, bottom;
int main(void)
{
// initialize raster IRQ
rirq_init(true);
// Build open border raster IRQ
rirq_build(&open, 1);
// Reduce vertical screen size to fool VIC counter
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);
// Build switch to normal raster IRQ
rirq_build(&bottom, 1);
rirq_write(&bottom, 0, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3 );
rirq_set(1, 50, &bottom);
// sort the raster IRQs
rirq_sort();
// start raster IRQ processing
rirq_start();
// Copy the sprite data
memcpy((char *)0x0380, spdata, 128);
// Initialize sprites
*(char *)(0x7f8) = 0x03c0 / 64;
*(char *)(0x7f9) = 0x0380 / 64;
*(char *)(0x7fa) = 0x03c0 / 64;
*(char *)(0x7fb) = 0x0380 / 64;
*(char *)(0x7fc) = 0x03c0 / 64;
*(char *)(0x7fd) = 0x0380 / 64;
*(char *)(0x7fe) = 0x03c0 / 64;
*(char *)(0x7ff) = 0x0380 / 64;
vic.spr_enable = 0b11111111;
vic.spr_multi = 0b10101010;
vic.spr_color[0] = VCOL_BLACK;
vic.spr_color[1] = VCOL_ORANGE;
vic.spr_color[2] = VCOL_BLACK;
vic.spr_color[3] = VCOL_ORANGE;
vic.spr_color[4] = VCOL_BLACK;
vic.spr_color[5] = VCOL_ORANGE;
vic.spr_color[6] = VCOL_BLACK;
vic.spr_color[7] = VCOL_ORANGE;
vic.spr_mcolor0 = VCOL_BROWN;
vic.spr_mcolor1 = VCOL_WHITE;
for(;;)
{
// Move sprites through all vertical positions
for(int i=0; i<255; i++)
{
vic_sprxy(0, 100, 1 * i); vic_sprxy(1, 100, 1 * i);
vic_sprxy(2, 140, 2 * i); vic_sprxy(3, 140, 2 * i);
vic_sprxy(4, 180, 3 * i); vic_sprxy(5, 180, 3 * i);
vic_sprxy(6, 220, 4 * i); vic_sprxy(7, 220, 4 * i);
rirq_wait();
}
}
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <string.h>
const char * Text =
S"LABORUM RERUM QUO. QUASI IN, SEQUI, TENETUR VOLUPTATEM RERUM "
S"PORRO NON ET MAIORES ALIAS ODIO EST EOS. MAGNAM APERIAM CUM ET "
S"ESSE TEMPORE ITAQUE TEMPORA VOLUPTAS ET IPSAM IPSAM EARUM. ID "
S"SUSCIPIT QUIA RERUM REPREHENDERIT ERROR ET UT. DOLOR ID "
S"CORPORIS, EOS? UNDE VERO ISTE QUIA? EAQUE EAQUE. IN. AUT ID "
S"EXPEDITA ILLUM MOLESTIAS, ";
// Raster interrupt command structure for change to scrolled and back
RIRQCode scroll, bottom;
int main(void)
{
// initialize raster IRQ
rirq_init(true);
// Build switch to scroll line IRQ
rirq_build(&scroll, 2);
// Delay for one line to get to right border
rirq_delay(&scroll, 11);
// Change control register two with this IRQ
rirq_write(&scroll, 1, &vic.ctrl2, 0);
// Put it onto the scroll line
rirq_set(0, 49 + 24 * 8, &scroll);
// Build the switch to normal IRQ
rirq_build(&bottom, 1);
// re-enable left and right column and reset horizontal scroll
rirq_write(&bottom, 0, &vic.ctrl2, VIC_CTRL2_CSEL);
// place this at the bottom
rirq_set(1, 250, &bottom);
// sort the raster IRQs
rirq_sort();
// start raster IRQ processing
rirq_start();
// Loop through text
int x = 0;
for(;;)
{
// wait for raster reaching bottom of screen
rirq_wait();
// Update raster IRQ for scroll line with new horizontal scroll offset
rirq_data(&scroll, 1, 7 - (x & 7));
// Copy scrolled version of text when switching over char border
if ((x & 7) == 0)
memcpy((char *)0x0400 + 40 * 24, Text + ((x >> 3) & 255), 40);
x++;
}
return 0;
}
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More