Fix crash in optimizer when declaring too many unused local variables
This commit is contained in:
parent
8b631d564e
commit
f56fb9e505
21
README.md
21
README.md
|
@ -672,6 +672,23 @@ Draws filled random circles and fills the space using flood fill.
|
|||
Similar to its hires counterpart but using four shades of grey.
|
||||
|
||||
|
||||
### Particle systems "particles"
|
||||
|
||||
Active hires graphics using particle system
|
||||
|
||||
#### Hires fireworks "fireworks_hires.c"
|
||||
|
||||
Simple hires particle system using velocity and gravity integration.
|
||||
|
||||
#### Multicolor fireworks "fireworks_ptr.c"
|
||||
|
||||
Simple multi color hires particle system using velocity and gravity integration.
|
||||
|
||||
#### Fireworks with striped memory layout "fireworks_stripe.c"
|
||||
|
||||
Simple multi color hires particle system using velocity and gravity integration. This version uses striped memory layout for the particles to simplify addressing for the CPU.
|
||||
|
||||
|
||||
### Mandelbrot renderer "fractals"
|
||||
|
||||
Various versions of the mandelbrot set using float arithmetic.
|
||||
|
@ -694,6 +711,10 @@ Multi color version using pure and mixed colors.
|
|||
|
||||
Mandelbrot rendered in 3D with shading. The image is drawn in columns from back to front, using two adjacent columns to calculate slope and brightness.
|
||||
|
||||
#### Interactive Navigate a fractal "mbzoom.c"
|
||||
|
||||
Navigate using WASD and zoom using + and -.
|
||||
|
||||
|
||||
### Raster beam interrupts "rasterirq"
|
||||
|
||||
|
|
|
@ -8792,24 +8792,24 @@ void InterCodeBasicBlock::MarkRelevantStatics(void)
|
|||
if (ins->mCode == IC_LOAD)
|
||||
{
|
||||
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL)
|
||||
ins->mSrc[0].mLinkerObject->mFlags |= LOBJF_RELEVANT;
|
||||
ins->mSrc[0].mLinkerObject->MarkRelevant();
|
||||
}
|
||||
else if (ins->mCode == IC_LEA)
|
||||
{
|
||||
if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL)
|
||||
ins->mSrc[1].mLinkerObject->mFlags |= LOBJF_RELEVANT;
|
||||
ins->mSrc[1].mLinkerObject->MarkRelevant();
|
||||
}
|
||||
else if (ins->mCode == IC_CONSTANT && ins->mDst.mType == IT_POINTER)
|
||||
{
|
||||
if (ins->mConst.mMemory == IM_GLOBAL)
|
||||
ins->mConst.mLinkerObject->mFlags |= LOBJF_RELEVANT;
|
||||
ins->mConst.mLinkerObject->MarkRelevant();
|
||||
}
|
||||
else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY)
|
||||
{
|
||||
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL)
|
||||
ins->mSrc[0].mLinkerObject->mFlags |= LOBJF_RELEVANT;
|
||||
ins->mSrc[0].mLinkerObject->MarkRelevant();
|
||||
if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL)
|
||||
ins->mSrc[1].mLinkerObject->mFlags |= LOBJF_RELEVANT;
|
||||
ins->mSrc[1].mLinkerObject->MarkRelevant();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13018,12 +13018,12 @@ void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory)
|
|||
{
|
||||
if (mLocalVars.Size() > 0 || mParamVars.Size() > 0)
|
||||
{
|
||||
for (int i = 0; i < mLocalVars.Size(); i++)
|
||||
for (int i = 0; i < mLocalAliasedSet.Size(); i++)
|
||||
{
|
||||
if (mLocalAliasedSet[i])
|
||||
mLocalVars[i]->mAliased = true;
|
||||
}
|
||||
for (int i = 0; i < mParamVars.Size(); i++)
|
||||
for (int i = 0; i < mParamAliasedSet.Size(); i++)
|
||||
{
|
||||
if (mParamAliasedSet[i])
|
||||
mParamVars[i]->mAliased = true;
|
||||
|
|
|
@ -43,6 +43,17 @@ void LinkerObject::AddReference(const LinkerReference& ref)
|
|||
mReferences.Push(nref);
|
||||
}
|
||||
|
||||
void LinkerObject::MarkRelevant(void)
|
||||
{
|
||||
if (!(mFlags & LOBJF_RELEVANT))
|
||||
{
|
||||
mFlags |= LOBJF_RELEVANT;
|
||||
for (int i = 0; i < mReferences.Size(); i++)
|
||||
if (mReferences[i]->mRefObject)
|
||||
mReferences[i]->mRefObject->MarkRelevant();
|
||||
}
|
||||
}
|
||||
|
||||
void LinkerObject::MoveToSection(LinkerSection* section)
|
||||
{
|
||||
if (section != mSection)
|
||||
|
|
|
@ -167,6 +167,8 @@ public:
|
|||
void AddReference(const LinkerReference& ref);
|
||||
|
||||
void MoveToSection(LinkerSection* section);
|
||||
|
||||
void MarkRelevant(void);
|
||||
};
|
||||
|
||||
class Linker
|
||||
|
|
|
@ -3038,9 +3038,16 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
#if 1
|
||||
if (mMode == ASMIM_ABSOLUTE_X && data.mRegs[CPU_REG_X].SameData(data.mRegs[CPU_REG_Y]) && HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_Y) && !(mFlags & NICT_INDEXFLIPPED))
|
||||
{
|
||||
mFlags |= NICT_INDEXFLIPPED;
|
||||
mMode = ASMIM_ABSOLUTE_Y;
|
||||
changed = true;
|
||||
}
|
||||
else if (mMode == ASMIM_ABSOLUTE_Y && data.mRegs[CPU_REG_X].SameData(data.mRegs[CPU_REG_Y]) && HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_X) && !(mFlags & NICT_INDEXFLIPPED))
|
||||
{
|
||||
mFlags |= NICT_INDEXFLIPPED;
|
||||
mMode = ASMIM_ABSOLUTE_X;
|
||||
changed = true;
|
||||
}
|
||||
#endif
|
||||
if (mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
|
@ -20966,6 +20973,23 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
|
|||
{
|
||||
AsmInsType carryop;
|
||||
|
||||
#if 1
|
||||
if (mIns[i].mMode == ASMIM_INDIRECT_Y && HasAsmInstructionMode(mIns[i].mType, ASMIM_ABSOLUTE_Y) &&
|
||||
mNDataSet.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE &&
|
||||
mNDataSet.mRegs[mIns[i].mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && (mNDataSet.mRegs[mIns[i].mAddress + 1].mFlags & NCIF_UPPER) &&
|
||||
mNDataSet.mRegs[mIns[i].mAddress].mMode != NRDM_IMMEDIATE_ADDRESS)
|
||||
{
|
||||
int reg = mIns[i].mAddress;
|
||||
mIns.Insert(i, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, reg));
|
||||
mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y;
|
||||
mIns[i + 1].mLinkerObject = mNDataSet.mRegs[reg + 1].mLinkerObject;
|
||||
mIns[i + 1].mAddress = mNDataSet.mRegs[reg + 1].mValue + mNDataSet.mRegs[CPU_REG_Y].mValue;
|
||||
mIns[i + 1].mFlags |= NCIF_LOWER;
|
||||
mIns.Insert(i + 2, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, mNDataSet.mRegs[CPU_REG_Y].mValue));
|
||||
mIns.Insert(i + 3, NativeCodeInstruction(ASMIT_ORA, ASMIM_IMMEDIATE, 0));
|
||||
changed = true;
|
||||
}
|
||||
#endif
|
||||
// Check load and commutative with current accu value
|
||||
#if 1
|
||||
if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress)
|
||||
|
@ -29339,21 +29363,19 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
}
|
||||
|
||||
#endif
|
||||
#if 1
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 1].mFlags & NCIF_UPPER) &&
|
||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
!(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
||||
}
|
||||
|
||||
if (i + 1 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 0].mFlags & NCIF_UPPER) &&
|
||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
proc->ResetPatched();
|
||||
if (CheckGlobalAddressSumYPointer(this, mIns[i + 1].mAddress - 1, mIns[i + 1].mAddress - 1, i + 2, -1))
|
||||
{
|
||||
proc->ResetPatched();
|
||||
if (CheckGlobalAddressSumYPointer(this, mIns[i + 1].mAddress - 1, mIns[i + 1].mAddress - 1, i + 2, -1))
|
||||
{
|
||||
proc->ResetPatched();
|
||||
if (PatchGlobalAddressSumYPointer(this, mIns[i + 1].mAddress - 1, mIns[i + 1].mAddress - 1, i + 2, -1, mIns[i + 0].mLinkerObject, mIns[i + 0].mAddress))
|
||||
progress = true;
|
||||
}
|
||||
if (PatchGlobalAddressSumYPointer(this, mIns[i + 1].mAddress - 1, mIns[i + 1].mAddress - 1, i + 2, -1, mIns[i + 0].mLinkerObject, mIns[i + 0].mAddress))
|
||||
progress = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (i + 5 < mIns.Size() &&
|
||||
|
|
|
@ -15,6 +15,10 @@ cd hiresmc
|
|||
./build.sh
|
||||
cd ..
|
||||
|
||||
cd particles
|
||||
./build.sh
|
||||
cd ..
|
||||
|
||||
cd kernalio
|
||||
./build.sh
|
||||
cd ..
|
||||
|
|
|
@ -4,4 +4,5 @@
|
|||
../../bin/oscar64 mbmulti.c -n
|
||||
../../bin/oscar64 mbmulti3d.c -n
|
||||
../../bin/oscar64 mbfixed.c -n -O3
|
||||
../../bin/oscar64 mbzoom.c -n -O3
|
||||
|
||||
|
|
|
@ -3,3 +3,4 @@ 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
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
#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];
|
||||
|
||||
#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 finaly 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,
|
||||
};
|
||||
|
||||
// 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 imaginery component
|
||||
long xx = sq(x), yy = sq(y), xxyy = sq(x + y);
|
||||
|
||||
// Use squares to check for exit condition of sure
|
||||
// to proress towards infinity
|
||||
if (xx + yy >= 4L * 4096 * 4096) return colors[i];
|
||||
|
||||
// Next iteration values using complex artithmetic
|
||||
// Mx' = Mx² - My² + Bx
|
||||
// My' = 2 * Mx * My + By = (Mx + My)² - Mx² - My² + By
|
||||
x = ((xx - yy + 2048) >> 12) + xz;
|
||||
y = ((xxyy - xx - yy + 2048) >> 12) + 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;
|
||||
|
||||
// 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;
|
||||
}
|
|
@ -14,6 +14,10 @@ cd hiresmc
|
|||
call make.bat
|
||||
cd ..
|
||||
|
||||
cd particles
|
||||
call make.bat
|
||||
cd ..
|
||||
|
||||
cd kernalio
|
||||
call make.bat
|
||||
cd ..
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
../../bin/oscar64 -n fireworks_ptr.c
|
||||
../../bin/oscar64 -n fireworks_hires.c
|
||||
../../bin/oscar64 -n fireworks_stripe.c
|
||||
|
|
@ -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 coordiate
|
||||
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 coordiate
|
||||
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;
|
||||
|
||||
}
|
|
@ -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 coordiate
|
||||
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 coordiate
|
||||
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 coordiate
|
||||
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 coordiate
|
||||
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;
|
||||
|
||||
}
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue