Fix LF line ending on windows, float and loop optimizations
This commit is contained in:
parent
9f41a55a18
commit
f25bf80a0f
|
@ -1,6 +1,6 @@
|
||||||
#include "joystick.h"
|
#include "joystick.h"
|
||||||
|
|
||||||
signed char joyx[2], joyy[2];
|
sbyte joyx[2], joyy[2];
|
||||||
bool joyb[2];
|
bool joyb[2];
|
||||||
|
|
||||||
void joy_poll(char n)
|
void joy_poll(char n)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#ifndef C64_JOYSTICK_H
|
#ifndef C64_JOYSTICK_H
|
||||||
#define C64_JOYSTICK_H
|
#define C64_JOYSTICK_H
|
||||||
|
|
||||||
extern signed char joyx[2], joyy[2];
|
#include "types.h"
|
||||||
|
|
||||||
|
extern sbyte joyx[2], joyy[2];
|
||||||
extern bool joyb[2];
|
extern bool joyb[2];
|
||||||
|
|
||||||
// poll joystick input for joystick 0 or 1 and place
|
// poll joystick input for joystick 0 or 1 and place
|
||||||
|
|
|
@ -245,6 +245,14 @@ void rirq_write(RIRQCode * ic, byte n, void * addr, byte data)
|
||||||
ic->code[p] = data;
|
ic->code[p] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rirq_call(RIRQCode * ic, byte n, void * addr)
|
||||||
|
{
|
||||||
|
byte p = irqai[n];
|
||||||
|
ic->code[p - 1] = 0x20;
|
||||||
|
ic->code[p + 0] = (unsigned)addr & 0xff;
|
||||||
|
ic->code[p + 1] = (unsigned)addr >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
void rirq_delay(RIRQCode * ic, byte cycles)
|
void rirq_delay(RIRQCode * ic, byte cycles)
|
||||||
{
|
{
|
||||||
ic->code[ 1] = cycles;
|
ic->code[ 1] = cycles;
|
||||||
|
|
|
@ -40,6 +40,9 @@ void rirq_build(RIRQCode * ic, byte size);
|
||||||
// Add a write command to a raster IRQ
|
// Add a write command to a raster IRQ
|
||||||
inline void rirq_write(RIRQCode * ic, byte n, void * addr, byte data);
|
inline void rirq_write(RIRQCode * ic, byte n, void * addr, byte data);
|
||||||
|
|
||||||
|
// Add a call command to a raster IRQ
|
||||||
|
inline void rirq_call(RIRQCode * ic, byte n, void * addr);
|
||||||
|
|
||||||
// Change the address of a raster IRQ write command
|
// Change the address of a raster IRQ write command
|
||||||
inline void rirq_addr(RIRQCode * ic, byte n, void * addr);
|
inline void rirq_addr(RIRQCode * ic, byte n, void * addr);
|
||||||
|
|
||||||
|
|
|
@ -2597,6 +2597,24 @@ bool InterInstruction::ConstantFolding(void)
|
||||||
mNumOperands = 1;
|
mNumOperands = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (mOperator == IA_MODU && (mSrc[0].mIntConst & (mSrc[0].mIntConst - 1)) == 0)
|
||||||
|
{
|
||||||
|
mOperator = IA_AND;
|
||||||
|
mSrc[0].mIntConst--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (mOperator == IA_DIVU && (mSrc[0].mIntConst & (mSrc[0].mIntConst - 1)) == 0)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
while (mSrc[0].mIntConst > 1)
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
mSrc[0].mIntConst >>= 1;
|
||||||
|
}
|
||||||
|
mOperator = IA_SHR;
|
||||||
|
mSrc[0].mIntConst = n;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mSrc[1].mTemp < 0)
|
else if (mSrc[1].mTemp < 0)
|
||||||
|
@ -3005,6 +3023,7 @@ void InterCodeBasicBlock::GenerateTraces(bool expand)
|
||||||
else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump))
|
else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump))
|
||||||
{
|
{
|
||||||
mTrueJump->mNumEntries--;
|
mTrueJump->mNumEntries--;
|
||||||
|
int n = mTrueJump->mNumEntries;
|
||||||
|
|
||||||
mInstructions.Pop();
|
mInstructions.Pop();
|
||||||
for (i = 0; i < mTrueJump->mInstructions.Size(); i++)
|
for (i = 0; i < mTrueJump->mInstructions.Size(); i++)
|
||||||
|
@ -3013,11 +3032,14 @@ void InterCodeBasicBlock::GenerateTraces(bool expand)
|
||||||
mFalseJump = mTrueJump->mFalseJump;
|
mFalseJump = mTrueJump->mFalseJump;
|
||||||
mTrueJump = mTrueJump->mTrueJump;
|
mTrueJump = mTrueJump->mTrueJump;
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
if (mTrueJump)
|
if (mTrueJump)
|
||||||
mTrueJump->mNumEntries++;
|
mTrueJump->mNumEntries++;
|
||||||
if (mFalseJump)
|
if (mFalseJump)
|
||||||
mFalseJump->mNumEntries++;
|
mFalseJump->mNumEntries++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3474,6 +3496,11 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
|
||||||
ins->mSrc[0].mIntConst = 3;
|
ins->mSrc[0].mIntConst = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ins->mOperator == IA_MODU && (ins->mSrc[0].mIntConst & (ins->mSrc[0].mIntConst - 1)) == 0)
|
||||||
|
{
|
||||||
|
ins->mOperator = IA_AND;
|
||||||
|
ins->mSrc[0].mIntConst--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ins->mSrc[0].mTemp > 0 && ins->mSrc[1].mTemp > 0 && ins->mSrc[0].mTemp == ins->mSrc[1].mTemp)
|
if (ins->mSrc[0].mTemp > 0 && ins->mSrc[1].mTemp > 0 && ins->mSrc[0].mTemp == ins->mSrc[1].mTemp)
|
||||||
|
@ -3915,6 +3942,17 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
|
||||||
{
|
{
|
||||||
mInstructions[i]->mOperator = IA_EXT8TO16U;
|
mInstructions[i]->mOperator = IA_EXT8TO16U;
|
||||||
}
|
}
|
||||||
|
else if (mInstructions[i]->mCode == IC_BINARY_OPERATOR && mInstructions[i]->mOperator == IA_DIVS && mInstructions[i]->mSrc[0].IsUnsigned() && mInstructions[i]->mSrc[1].IsUnsigned())
|
||||||
|
{
|
||||||
|
mInstructions[i]->mOperator = IA_DIVU;
|
||||||
|
mInstructions[i]->ConstantFolding();
|
||||||
|
}
|
||||||
|
else if (mInstructions[i]->mCode == IC_BINARY_OPERATOR && mInstructions[i]->mOperator == IA_MODS && mInstructions[i]->mSrc[0].IsUnsigned() && mInstructions[i]->mSrc[1].IsUnsigned())
|
||||||
|
{
|
||||||
|
mInstructions[i]->mOperator = IA_MODU;
|
||||||
|
mInstructions[i]->ConstantFolding();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6655,16 +6693,16 @@ void InterCodeBasicBlock::FollowJumps(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
InterCodeBasicBlock* InterCodeBasicBlock::PropagateDominator(InterCodeProcedure* proc)
|
InterCodeBasicBlock* InterCodeBasicBlock::BuildLoopPrefix(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
{
|
{
|
||||||
mVisited = true;
|
mVisited = true;
|
||||||
|
|
||||||
if (mTrueJump)
|
if (mTrueJump)
|
||||||
mTrueJump = mTrueJump->PropagateDominator(proc);
|
mTrueJump = mTrueJump->BuildLoopPrefix(proc);
|
||||||
if (mFalseJump)
|
if (mFalseJump)
|
||||||
mFalseJump = mFalseJump->PropagateDominator(proc);
|
mFalseJump = mFalseJump->BuildLoopPrefix(proc);
|
||||||
|
|
||||||
if (mLoopHead)
|
if (mLoopHead)
|
||||||
{
|
{
|
||||||
|
@ -8458,7 +8496,7 @@ void InterCodeProcedure::Close(void)
|
||||||
TempForwarding();
|
TempForwarding();
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildDominators();
|
BuildLoopPrefix();
|
||||||
DisassembleDebug("added dominators");
|
DisassembleDebug("added dominators");
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
@ -8655,6 +8693,21 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
BuildLoopPrefix();
|
||||||
|
DisassembleDebug("added dominators");
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet);
|
||||||
|
|
||||||
|
DisassembleDebug("single block loop opt 2");
|
||||||
|
|
||||||
|
BuildDataFlowSets();
|
||||||
|
|
||||||
|
BuildTraces(false);
|
||||||
|
DisassembleDebug("Rebuilt traces");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->PeepholeOptimization();
|
mEntryBlock->PeepholeOptimization();
|
||||||
|
@ -8848,10 +8901,14 @@ void InterCodeProcedure::MergeBasicBlocks(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterCodeProcedure::BuildDominators(void)
|
void InterCodeProcedure::BuildLoopPrefix(void)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock = mEntryBlock->PropagateDominator(this);
|
|
||||||
|
for (int i = 0; i < mBlocks.Size(); i++)
|
||||||
|
mBlocks[i]->mLoopPrefix = nullptr;
|
||||||
|
|
||||||
|
mEntryBlock = mEntryBlock->BuildLoopPrefix(this);
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
for (int i = 0; i < mBlocks.Size(); i++)
|
for (int i = 0; i < mBlocks.Size(); i++)
|
||||||
|
@ -9002,7 +9059,7 @@ void InterCodeProcedure::Disassemble(FILE* file)
|
||||||
static char typechars[] = "NBCILFP";
|
static char typechars[] = "NBCILFP";
|
||||||
for (int i = 0; i < mTemporaries.Size(); i++)
|
for (int i = 0; i < mTemporaries.Size(); i++)
|
||||||
{
|
{
|
||||||
fprintf(file, "$%02x T%d(%c), ", mTempOffset[i], i, typechars[mTemporaries[i]]);
|
fprintf(file, "$%02x R%d(%c), ", mTempOffset[i], i, typechars[mTemporaries[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(file, "\n");
|
fprintf(file, "\n");
|
||||||
|
|
|
@ -445,7 +445,7 @@ public:
|
||||||
void CollectLoopPath(const GrowingArray<InterCodeBasicBlock*>& body, GrowingArray<InterCodeBasicBlock*>& path);
|
void CollectLoopPath(const GrowingArray<InterCodeBasicBlock*>& body, GrowingArray<InterCodeBasicBlock*>& path);
|
||||||
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
||||||
|
|
||||||
InterCodeBasicBlock* PropagateDominator(InterCodeProcedure * proc);
|
InterCodeBasicBlock* BuildLoopPrefix(InterCodeProcedure * proc);
|
||||||
|
|
||||||
void SplitBranches(InterCodeProcedure* proc);
|
void SplitBranches(InterCodeProcedure* proc);
|
||||||
void FollowJumps(void);
|
void FollowJumps(void);
|
||||||
|
@ -517,7 +517,7 @@ protected:
|
||||||
void TempForwarding(void);
|
void TempForwarding(void);
|
||||||
void RemoveUnusedInstructions(void);
|
void RemoveUnusedInstructions(void);
|
||||||
bool GlobalConstantPropagation(void);
|
bool GlobalConstantPropagation(void);
|
||||||
void BuildDominators(void);
|
void BuildLoopPrefix(void);
|
||||||
void SingleAssignmentForwarding(void);
|
void SingleAssignmentForwarding(void);
|
||||||
|
|
||||||
void MergeBasicBlocks(void);
|
void MergeBasicBlocks(void);
|
||||||
|
|
|
@ -5106,6 +5106,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
{
|
{
|
||||||
int sop0 = 0, sop1 = 1;
|
int sop0 = 0, sop1 = 1;
|
||||||
bool flipop = false;
|
bool flipop = false;
|
||||||
|
bool changedSign = false;
|
||||||
|
|
||||||
if (ins->mOperator == IA_ADD || ins->mOperator == IA_MUL || ins->mOperator == IA_SUB)
|
if (ins->mOperator == IA_ADD || ins->mOperator == IA_MUL || ins->mOperator == IA_SUB)
|
||||||
{
|
{
|
||||||
|
@ -5128,6 +5129,13 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
if (ins->mSrc[sop1].mTemp < 0)
|
if (ins->mSrc[sop1].mTemp < 0)
|
||||||
{
|
{
|
||||||
union { float f; unsigned int v; } cc;
|
union { float f; unsigned int v; } cc;
|
||||||
|
|
||||||
|
if (ins->mOperator == IA_SUB && flipop)
|
||||||
|
{
|
||||||
|
changedSign = true;
|
||||||
|
cc.f = -ins->mSrc[sop1].mFloatConst;
|
||||||
|
}
|
||||||
|
else
|
||||||
cc.f = ins->mSrc[sop1].mFloatConst;
|
cc.f = ins->mSrc[sop1].mFloatConst;
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
||||||
|
@ -5168,6 +5176,13 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
if (ins->mSrc[sop0].mTemp < 0)
|
if (ins->mSrc[sop0].mTemp < 0)
|
||||||
{
|
{
|
||||||
union { float f; unsigned int v; } cc;
|
union { float f; unsigned int v; } cc;
|
||||||
|
|
||||||
|
if (ins->mOperator == IA_SUB && !flipop)
|
||||||
|
{
|
||||||
|
changedSign = true;
|
||||||
|
cc.f = -ins->mSrc[sop0].mFloatConst;
|
||||||
|
}
|
||||||
|
else
|
||||||
cc.f = ins->mSrc[sop0].mFloatConst;
|
cc.f = ins->mSrc[sop0].mFloatConst;
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
||||||
|
@ -5213,6 +5228,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
||||||
} break;
|
} break;
|
||||||
case IA_SUB:
|
case IA_SUB:
|
||||||
|
{
|
||||||
|
if (!changedSign)
|
||||||
{
|
{
|
||||||
if (flipop)
|
if (flipop)
|
||||||
{
|
{
|
||||||
|
@ -5226,6 +5243,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("faddsub")));
|
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("faddsub")));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
||||||
|
@ -15103,18 +15121,34 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
|
if (commonFrameSize >= 256)
|
||||||
|
{
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCS, ASMIM_RELATIVE, 2));
|
||||||
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
|
}
|
||||||
|
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
|
if (commonFrameSize >= 256)
|
||||||
|
{
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2));
|
||||||
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mNoFrame)
|
if (mNoFrame)
|
||||||
{
|
{
|
||||||
|
|
|
@ -88,7 +88,7 @@ bool SourceFile::Open(const char* name, const char* path, bool binary)
|
||||||
|
|
||||||
strcat_s(fname + n, sizeof(fname) - n, name);
|
strcat_s(fname + n, sizeof(fname) - n, name);
|
||||||
|
|
||||||
if (!fopen_s(&mFile, fname, binary ? "rb" : "r"))
|
if (!fopen_s(&mFile, fname, "rb"))
|
||||||
{
|
{
|
||||||
_fullpath(mFileName, fname, sizeof(mFileName));
|
_fullpath(mFileName, fname, sizeof(mFileName));
|
||||||
char* p = mFileName;
|
char* p = mFileName;
|
||||||
|
@ -158,7 +158,7 @@ bool Preprocessor::NextLine(void)
|
||||||
mLocation.mLine++;
|
mLocation.mLine++;
|
||||||
|
|
||||||
s = strlen(mLine);
|
s = strlen(mLine);
|
||||||
while (s > 0 && mLine[s - 1] == '\n')
|
while (s > 0 && (mLine[s - 1] == '\n' || mLine[s - 1] == '\r'))
|
||||||
s--;
|
s--;
|
||||||
if (s == 0 || mLine[s - 1] != '\\')
|
if (s == 0 || mLine[s - 1] != '\\')
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -73,7 +73,7 @@ int main(int argc, const char** argv)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
strcpy(strProductName, "oscar64");
|
strcpy(strProductName, "oscar64");
|
||||||
strcpy(strProductVersion, "1.2.66");
|
strcpy(strProductVersion, "1.2.67");
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
uint32_t length = sizeof(basePath);
|
uint32_t length = sizeof(basePath);
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,2,66,0
|
FILEVERSION 1,2,67,0
|
||||||
PRODUCTVERSION 1,2,66,0
|
PRODUCTVERSION 1,2,67,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -43,12 +43,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "oscar64"
|
VALUE "CompanyName", "oscar64"
|
||||||
VALUE "FileDescription", "oscar64 compiler"
|
VALUE "FileDescription", "oscar64 compiler"
|
||||||
VALUE "FileVersion", "1.2.66.0"
|
VALUE "FileVersion", "1.2.67.0"
|
||||||
VALUE "InternalName", "oscar64.exe"
|
VALUE "InternalName", "oscar64.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||||
VALUE "OriginalFilename", "oscar64.exe"
|
VALUE "OriginalFilename", "oscar64.exe"
|
||||||
VALUE "ProductName", "oscar64"
|
VALUE "ProductName", "oscar64"
|
||||||
VALUE "ProductVersion", "1.2.66.0"
|
VALUE "ProductVersion", "1.2.67.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -3169,15 +3169,15 @@
|
||||||
{
|
{
|
||||||
"Name" = "8:Microsoft Visual Studio"
|
"Name" = "8:Microsoft Visual Studio"
|
||||||
"ProductName" = "8:oscar64"
|
"ProductName" = "8:oscar64"
|
||||||
"ProductCode" = "8:{71F1F5C2-A7B5-46C1-8354-C7B870ADCD34}"
|
"ProductCode" = "8:{118A6EF7-D160-4A3E-AECC-5B0D9AA16099}"
|
||||||
"PackageCode" = "8:{7F48C21E-E13E-479D-824A-5AB731A09EB1}"
|
"PackageCode" = "8:{8B7C9187-A38D-43DB-B458-3E80FDB17616}"
|
||||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||||
"AspNetVersion" = "8:2.0.50727.0"
|
"AspNetVersion" = "8:2.0.50727.0"
|
||||||
"RestartWWWService" = "11:FALSE"
|
"RestartWWWService" = "11:FALSE"
|
||||||
"RemovePreviousVersions" = "11:TRUE"
|
"RemovePreviousVersions" = "11:TRUE"
|
||||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||||
"InstallAllUsers" = "11:FALSE"
|
"InstallAllUsers" = "11:FALSE"
|
||||||
"ProductVersion" = "8:1.2.66"
|
"ProductVersion" = "8:1.2.67"
|
||||||
"Manufacturer" = "8:oscar64"
|
"Manufacturer" = "8:oscar64"
|
||||||
"ARPHELPTELEPHONE" = "8:"
|
"ARPHELPTELEPHONE" = "8:"
|
||||||
"ARPHELPLINK" = "8:"
|
"ARPHELPLINK" = "8:"
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
call ..\..\bin\oscar64 snake.c
|
||||||
|
call ..\..\bin\oscar64 -n lander.c
|
|
@ -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
|
||||||
|
bool 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;
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue