73 lines
2.2 KiB
C
73 lines
2.2 KiB
C
|
|
/*----------------------------------------------------------------------+
|
|
| |
|
|
| Horizon.c -- Interactive 3D demo in C |
|
|
| |
|
|
+----------------------------------------------------------------------*/
|
|
|
|
// Standard includes
|
|
#include <stdio.h>
|
|
#include <gigatron/sys.h>
|
|
|
|
#define screenWidth 160
|
|
#define screenHeight 120
|
|
#define horizonY 32
|
|
#define maxPitch (256 - screenWidth) // Aim for max possible pitch at bottom
|
|
#define color1 0x3f
|
|
#define color2 0x03
|
|
#define maxV 32
|
|
|
|
int main(void)
|
|
{
|
|
int y, x, i, j, v = 8;
|
|
byte *p, *q = &videoTable[240];
|
|
|
|
#define makeEven(v) (((v) + 1) & ~1) // Odd pitches give jagged edges?
|
|
#define calcPitch(y) makeEven((y) + (maxPitch - screenHeight + 1))
|
|
|
|
// Draw tiles in perspective in screen memory
|
|
for (y=screenHeight-1; y>=horizonY; y--) {
|
|
int pitch = calcPitch(y);
|
|
int width = screenWidth + pitch;
|
|
i = (screenWidth/2) % pitch;
|
|
j = (400 / (y-horizonY+40)) & 1 ? 0 : color1^color2; // Swap colors
|
|
for (x=0; x<width; x++) {
|
|
if (i-- == 0)
|
|
i = pitch - 1;
|
|
screenMemory[y][x] = (i+i >= pitch) ? color1^j : color2^j;
|
|
}
|
|
videoTop_v5 = y+y; // Safe no-op on ROMs without videoTop
|
|
}
|
|
videoTop_v5 = 0; // Show all
|
|
|
|
// Interactive animation
|
|
for (x=0; ; x+=v) {
|
|
i = x & 255; // Phase i
|
|
|
|
// Calculate horizontal shift j at horizon
|
|
for (y=0,j=0; y<calcPitch(horizonY); y++)
|
|
j += i;
|
|
|
|
// Quickly update videoTable, in steps of 2 pixel lines for more speed
|
|
p = &videoTable[horizonY*2+1];
|
|
i += i;
|
|
|
|
// Synchronize with vertical blank
|
|
{ byte nextFrame = frameCount + 1;
|
|
while (frameCount != nextFrame) /**/ ; }
|
|
|
|
for (; p<q; p+=4) {
|
|
*p = j >> 8; // LCC nicely emits LD vAC+1 for the shift
|
|
j = i + (j & 255); // Faster operand order for LCC...
|
|
}
|
|
|
|
// Change speed by game controller or keys
|
|
switch (buttonState) {
|
|
case buttonRight: if (++v > maxV) v = maxV; break;
|
|
case buttonLeft: if (--v < -maxV) v = -maxV; break;
|
|
case buttonA: case buttonB: v = 0; break;
|
|
}
|
|
}
|
|
}
|
|
|