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.
|
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"
|
### Mandelbrot renderer "fractals"
|
||||||
|
|
||||||
Various versions of the mandelbrot set using float arithmetic.
|
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.
|
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"
|
### Raster beam interrupts "rasterirq"
|
||||||
|
|
||||||
|
|
|
@ -8792,24 +8792,24 @@ void InterCodeBasicBlock::MarkRelevantStatics(void)
|
||||||
if (ins->mCode == IC_LOAD)
|
if (ins->mCode == IC_LOAD)
|
||||||
{
|
{
|
||||||
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL)
|
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)
|
else if (ins->mCode == IC_LEA)
|
||||||
{
|
{
|
||||||
if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL)
|
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)
|
else if (ins->mCode == IC_CONSTANT && ins->mDst.mType == IT_POINTER)
|
||||||
{
|
{
|
||||||
if (ins->mConst.mMemory == IM_GLOBAL)
|
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)
|
else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY)
|
||||||
{
|
{
|
||||||
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL)
|
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)
|
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)
|
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])
|
if (mLocalAliasedSet[i])
|
||||||
mLocalVars[i]->mAliased = true;
|
mLocalVars[i]->mAliased = true;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < mParamVars.Size(); i++)
|
for (int i = 0; i < mParamAliasedSet.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mParamAliasedSet[i])
|
if (mParamAliasedSet[i])
|
||||||
mParamVars[i]->mAliased = true;
|
mParamVars[i]->mAliased = true;
|
||||||
|
|
|
@ -43,6 +43,17 @@ void LinkerObject::AddReference(const LinkerReference& ref)
|
||||||
mReferences.Push(nref);
|
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)
|
void LinkerObject::MoveToSection(LinkerSection* section)
|
||||||
{
|
{
|
||||||
if (section != mSection)
|
if (section != mSection)
|
||||||
|
|
|
@ -167,6 +167,8 @@ public:
|
||||||
void AddReference(const LinkerReference& ref);
|
void AddReference(const LinkerReference& ref);
|
||||||
|
|
||||||
void MoveToSection(LinkerSection* section);
|
void MoveToSection(LinkerSection* section);
|
||||||
|
|
||||||
|
void MarkRelevant(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Linker
|
class Linker
|
||||||
|
|
|
@ -3038,9 +3038,16 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
#if 1
|
#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))
|
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;
|
mMode = ASMIM_ABSOLUTE_Y;
|
||||||
changed = true;
|
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
|
#endif
|
||||||
if (mMode == ASMIM_ZERO_PAGE)
|
if (mMode == ASMIM_ZERO_PAGE)
|
||||||
{
|
{
|
||||||
|
@ -20966,6 +20973,23 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
|
||||||
{
|
{
|
||||||
AsmInsType carryop;
|
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
|
// Check load and commutative with current accu value
|
||||||
#if 1
|
#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)
|
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
|
#endif
|
||||||
#if 1
|
}
|
||||||
else if (
|
|
||||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 1].mFlags & NCIF_UPPER) &&
|
if (i + 1 < mIns.Size() &&
|
||||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 0].mFlags & NCIF_UPPER) &&
|
||||||
!(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
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();
|
proc->ResetPatched();
|
||||||
if (CheckGlobalAddressSumYPointer(this, mIns[i + 1].mAddress - 1, mIns[i + 1].mAddress - 1, i + 2, -1))
|
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;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i + 5 < mIns.Size() &&
|
if (i + 5 < mIns.Size() &&
|
||||||
|
|
|
@ -15,6 +15,10 @@ cd hiresmc
|
||||||
./build.sh
|
./build.sh
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
cd particles
|
||||||
|
./build.sh
|
||||||
|
cd ..
|
||||||
|
|
||||||
cd kernalio
|
cd kernalio
|
||||||
./build.sh
|
./build.sh
|
||||||
cd ..
|
cd ..
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
../../bin/oscar64 mbmulti.c -n
|
../../bin/oscar64 mbmulti.c -n
|
||||||
../../bin/oscar64 mbmulti3d.c -n
|
../../bin/oscar64 mbmulti3d.c -n
|
||||||
../../bin/oscar64 mbfixed.c -n -O3
|
../../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 mbmulti.c -n
|
||||||
call ..\..\bin\oscar64 mbmulti3d.c -n
|
call ..\..\bin\oscar64 mbmulti3d.c -n
|
||||||
call ..\..\bin\oscar64 mbfixed.c -n -O3
|
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
|
call make.bat
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
cd particles
|
||||||
|
call make.bat
|
||||||
|
cd ..
|
||||||
|
|
||||||
cd kernalio
|
cd kernalio
|
||||||
call make.bat
|
call make.bat
|
||||||
cd ..
|
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