Add horizontal scroll shmup sample game

This commit is contained in:
drmortalwombat 2022-03-06 21:49:10 +01:00
parent d1104e1eb3
commit c5fc186336
16 changed files with 867 additions and 346 deletions

131
include/audio/sidfx.c Normal file
View File

@ -0,0 +1,131 @@
#include "sidfx.h"
enum SIDFXState
{
SIDFX_IDLE,
SIDFX_RESET_0,
SIDFX_RESET_1,
SIDFX_READY,
SIDFX_PLAY,
SIDFX_WAIT
};
static struct SIDFXChannel
{
SIDFX * com;
byte delay, cnt;
SIDFXState state;
unsigned freq;
} channels[3];
void sidfx_init(void)
{
for(char i=0; i<3; i++)
{
channels[i].com = nullptr;
channels[i].state = SIDFX_IDLE;
}
}
void sidfx_play(byte chn, SIDFX * fx, byte cnt)
{
if (channels[chn].state == SIDFX_IDLE)
channels[chn].state = SIDFX_READY;
else
channels[chn].state = SIDFX_RESET_0;
channels[chn].com = fx;
channels[chn].cnt = cnt - 1;
}
void sidfx_stop(byte chn)
{
channels[chn].com = nullptr;
if (channels[chn].state != SIDFX_IDLE)
channels[chn].state = SIDFX_RESET_0;
}
void sidfx_loop(void)
{
for(byte ch=0; ch<3; ch++)
{
switch (channels[ch].state)
{
case SIDFX_IDLE:
break;
case SIDFX_RESET_0:
sid.voices[ch].ctrl = 0;
sid.voices[ch].attdec = 0;
sid.voices[ch].susrel = 0;
channels[ch].state = SIDFX_RESET_1;
break;
case SIDFX_RESET_1:
sid.voices[ch].ctrl = SID_CTRL_TEST;
channels[ch].state = SIDFX_READY;
break;
case SIDFX_READY:
if (channels[ch].com)
{
channels[ch].freq = channels[ch].com->freq;
sid.voices[ch].freq = channels[ch].com->freq;
sid.voices[ch].pwm = channels[ch].com->pwm;
sid.voices[ch].attdec = channels[ch].com->attdec;
sid.voices[ch].susrel = channels[ch].com->susrel;
sid.voices[ch].ctrl = channels[ch].com->ctrl;
channels[ch].delay = channels[ch].com->time1;
channels[ch].state = SIDFX_PLAY;
}
else
channels[ch].state = SIDFX_IDLE;
break;
case SIDFX_PLAY:
if (channels[ch].com->dfreq)
{
channels[ch].freq += channels[ch].com->dfreq;
sid.voices[ch].freq = channels[ch].freq;
}
if (channels[ch].delay)
channels[ch].delay--;
else if (channels[ch].com->time0)
{
sid.voices[ch].ctrl = channels[ch].com->ctrl & ~SID_CTRL_GATE;
channels[ch].delay = channels[ch].com->time0;
channels[ch].state = SIDFX_WAIT;
}
else if (channels[ch].cnt)
{
channels[ch].cnt--;
channels[ch].com++;
channels[ch].state = SIDFX_READY;
}
else
{
channels[ch].com = nullptr;
channels[ch].state = SIDFX_RESET_0;
}
break;
case SIDFX_WAIT:
if (channels[ch].com->dfreq)
{
channels[ch].freq += channels[ch].com->dfreq;
sid.voices[ch].freq = channels[ch].freq;
}
if (channels[ch].delay)
channels[ch].delay--;
else if (channels[ch].cnt)
{
channels[ch].cnt--;
channels[ch].com++;
channels[ch].state = SIDFX_RESET_0;
}
else
{
channels[ch].com = nullptr;
channels[ch].state = SIDFX_RESET_0;
}
break;
}
}
}

24
include/audio/sidfx.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef SIDFX_H
#define SIDFX_H
#include <c64/sid.h>
struct SIDFX
{
unsigned freq, pwm;
byte ctrl, attdec, susrel;
sbyte dfreq, dpwm;
byte time1, time0;
};
void sidfx_init(void);
void sidfx_play(byte chn, SIDFX * fx, byte cnt);
void sidfx_stop(byte chn);
void sidfx_loop(void);
#pragma compile("sidfx.c")
#endif

View File

@ -728,6 +728,23 @@ bool NativeCodeInstruction::ChangesZeroPage(int address) const
{
if (mMode == ASMIM_ZERO_PAGE && mAddress == address)
return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || mType == ASMIT_STA || mType == ASMIT_STX || mType == ASMIT_STY;
else if (mType == ASMIT_JSR)
{
if (address >= BC_REG_ACCU && address < BC_REG_ACCU + 4)
return true;
if (address >= BC_REG_WORK && address < BC_REG_WORK + 8)
return true;
if (!(mFlags & NCIF_RUNTIME) || (mFlags & NCIF_FEXEC))
{
if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END)
return true;
if (address >= BC_REG_TMP && address < BC_REG_TMP_SAVED)
return true;
}
return false;
}
else
return false;
}
@ -924,6 +941,41 @@ bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
return false;
}
bool NativeCodeInstruction::MayBeSameAddress(const NativeCodeInstruction& ins) const
{
if (ins.mMode == ASMIM_ZERO_PAGE)
{
if (mMode == ASMIM_ZERO_PAGE)
return mAddress == ins.mAddress;
else
return false;
}
else if (ins.mMode == ASMIM_ZERO_PAGE_X || ins.mMode == ASMIM_ZERO_PAGE_Y)
{
return mMode == ASMIM_ZERO_PAGE || mMode == ASMIM_INDIRECT_X || mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_ZERO_PAGE_X || mMode == ASMIM_ZERO_PAGE_Y;
}
else if (ins.mMode == ASMIM_ABSOLUTE)
{
if (mMode == ASMIM_ABSOLUTE)
return mLinkerObject == ins.mLinkerObject && mAddress == ins.mAddress;
else if (mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
return mLinkerObject == ins.mLinkerObject;
else
return mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X;
}
else if (ins.mMode == ASMIM_ABSOLUTE_X || ins.mMode == ASMIM_ABSOLUTE_Y)
{
if (mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
return mLinkerObject == ins.mLinkerObject;
else
return mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X;
}
else if (ins.mMode == ASMIM_INDIRECT_Y || ins.mMode == ASMIM_INDIRECT_X)
return mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y || mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X;
else
return false;
}
bool NativeCodeInstruction::MayBeChangedOnAddress(const NativeCodeInstruction& ins) const
{
if (!ins.ChangesAddress())
@ -9937,6 +9989,27 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc)
}
}
#endif
#if 1
if (mIns.Size() >= 1 && mIns.Last().mType == ASMIT_STA && mIns.Last().mMode == ASMIM_ZERO_PAGE && mTrueJump && mFalseJump)
{
const NativeCodeInstruction& ins(mIns.Last());
if (mTrueJump->mEntryRequiredRegs[ins.mAddress] && !mFalseJump->mEntryRequiredRegs[ins.mAddress] && mTrueJump->mEntryBlocks.Size() == 1)
{
mTrueJump->mIns.Insert(0, ins);
mIns.Remove(mIns.Size() - 1);
mTrueJump->mEntryRequiredRegs += CPU_REG_A;
changed = true;
}
else if (mFalseJump->mEntryRequiredRegs[ins.mAddress] && !mTrueJump->mEntryRequiredRegs[ins.mAddress] && mFalseJump->mEntryBlocks.Size() == 1)
{
mFalseJump->mIns.Insert(0, ins);
mIns.Remove(mIns.Size() - 1);
mFalseJump->mEntryRequiredRegs += CPU_REG_A;
changed = true;
}
}
#endif
#if 1
if (mTrueJump && mFalseJump && !mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump)
{
@ -10113,10 +10186,10 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ
{
if (!mPatched)
{
mPatched = true;
if (at == 0)
{
mPatched = true;
if (!mEntryRequiredRegs[reg])
return true;
@ -11501,9 +11574,11 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
}
if (mIns[j].ChangesZeroPage(mIns[at].mAddress))
return false;
if (mIns[j].ChangesGlobalMemory())
if (mIns[j].MayBeSameAddress(mIns[at + 1]))
return false;
if (mIns[j].SameEffectiveAddress(mIns[at + 1]))
if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_X && mIns[j].ChangesXReg())
return false;
if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg())
return false;
j--;
@ -14260,7 +14335,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#if 1
// move load (),y store zp down to potential user
for (int i = 2; i + 2 < mIns.Size(); i++)
for (int i = 2; i + 1 < mIns.Size(); i++)
{
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
@ -14277,7 +14352,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
for (int i = 2; i + 1 < mIns.Size(); i++)
{
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA &&
(mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y) &&
!(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
if (MoveAbsoluteLoadStoreUp(i))
changed = true;

View File

@ -106,6 +106,7 @@ public:
bool ChangesGlobalMemory(void) const;
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
bool MayBeChangedOnAddress(const NativeCodeInstruction& ins) const;
bool MayBeSameAddress(const NativeCodeInstruction& ins) const;
bool IsSame(const NativeCodeInstruction& ins) const;
bool IsCommutative(void) const;
bool IsShift(void) const;

View File

@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
#else
strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.4.98");
strcpy(strProductVersion, "1.4.99");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,98,0
PRODUCTVERSION 1,4,98,0
FILEVERSION 1,4,99,0
PRODUCTVERSION 1,4,99,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.4.98.0"
VALUE "FileVersion", "1.4.99.0"
VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.4.98.0"
VALUE "ProductVersion", "1.4.99.0"
END
END
BLOCK "VarFileInfo"

View File

@ -34,12 +34,6 @@
}
"Entry"
{
"MsmKey" = "8:_03D7013B0D39A89CEA9D267005ADCE39"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_04ABABC55200450383686DD782DD1548"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -64,6 +58,12 @@
}
"Entry"
{
"MsmKey" = "8:_0CC2E11595B34DF0A003DF534A5AADF5"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_0D8B657E4A954DBFAF14055CDFFB384C"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -154,12 +154,6 @@
}
"Entry"
{
"MsmKey" = "8:_326B44043E3720E0A341FB5627DA8873"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_3277DE1463544F67B7E7390175F8A9CF"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -172,12 +166,6 @@
}
"Entry"
{
"MsmKey" = "8:_36B4A1247BFCE001E1BAE7560E9CFEEA"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_379EE3C17FEC4C5EA79D07668CD05FC4"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -250,12 +238,6 @@
}
"Entry"
{
"MsmKey" = "8:_458189403F0009BC49371204B74F3BD3"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_47A877D439EE429BAB64C52FEF69EDA4"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -274,6 +256,12 @@
}
"Entry"
{
"MsmKey" = "8:_4CAC4169D7CC4A2099042927E32B2184"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_539501D7FC4941B8AEE943A2D5C74703"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -322,6 +310,12 @@
}
"Entry"
{
"MsmKey" = "8:_652D33F4F54F4974AA6C4CD23A323FD1"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_67C8F824E02B4211B315AB32AB7ABBB1"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -358,8 +352,8 @@
}
"Entry"
{
"MsmKey" = "8:_749A2BA18335F50EB53CCE7029861FBC"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmKey" = "8:_7393641DDDD742BCA845F192181E1294"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
@ -418,8 +412,8 @@
}
"Entry"
{
"MsmKey" = "8:_8667075410229C38BF63AC1CC776055E"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmKey" = "8:_814F6BFC9788449DB259F99386D39AFD"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
@ -586,6 +580,12 @@
}
"Entry"
{
"MsmKey" = "8:_B59AF91A39B749DF9E6B95CD35C5C6AC"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_B85448D515F0487FB6845119AE346F1D"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -694,6 +694,12 @@
}
"Entry"
{
"MsmKey" = "8:_D2CCF52F2336415EAD896A2C5410D5E8"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_D34AB6F4EE6C4E18A8C6D44CC8E23CB7"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -718,12 +724,6 @@
}
"Entry"
{
"MsmKey" = "8:_DD5A4DD822437085CD584319732F2D4D"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_DEADBEA270134B77800770802B21859C"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -784,12 +784,6 @@
}
"Entry"
{
"MsmKey" = "8:_EA3C0BCB01F2639DFA2E37EC8436E5F6"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_ED872D39D58443D590B7C80604BC0FF4"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -820,12 +814,6 @@
}
"Entry"
{
"MsmKey" = "8:_F20F5618C7576D758C01D89C87469AF8"
"OwnerKey" = "8:_FB2E467BC172457785F4279BB0BFE8B6"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_F35970F9D8FA46B09F36D7E9DE5532CA"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -1001,26 +989,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_03D7013B0D39A89CEA9D267005ADCE39"
{
"SourcePath" = "8:VCRUNTIME140.dll"
"TargetName" = "8:VCRUNTIME140.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_04ABABC55200450383686DD782DD1548"
{
"SourcePath" = "8:..\\samples\\games\\lander.c"
@ -1101,6 +1069,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0CC2E11595B34DF0A003DF534A5AADF5"
{
"SourcePath" = "8:..\\include\\audio\\sidfx.h"
"TargetName" = "8:sidfx.h"
"Tag" = "8:"
"Folder" = "8:_A4C8078BC7A74CCABB1050E80BC79950"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0D8B657E4A954DBFAF14055CDFFB384C"
{
"SourcePath" = "8:..\\include\\crt.c"
@ -1401,26 +1389,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_326B44043E3720E0A341FB5627DA8873"
{
"SourcePath" = "8:api-ms-win-crt-stdio-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-stdio-l1-1-0.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3277DE1463544F67B7E7390175F8A9CF"
{
"SourcePath" = "8:..\\samples\\rasterirq\\autocrawler.c"
@ -1461,26 +1429,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_36B4A1247BFCE001E1BAE7560E9CFEEA"
{
"SourcePath" = "8:api-ms-win-crt-math-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-math-l1-1-0.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_379EE3C17FEC4C5EA79D07668CD05FC4"
{
"SourcePath" = "8:..\\samples\\memmap\\easyflash.c"
@ -1721,26 +1669,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_458189403F0009BC49371204B74F3BD3"
{
"SourcePath" = "8:api-ms-win-crt-string-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-string-l1-1-0.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_47A877D439EE429BAB64C52FEF69EDA4"
{
"SourcePath" = "8:..\\samples\\memmap\\largemem.c"
@ -1801,6 +1729,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4CAC4169D7CC4A2099042927E32B2184"
{
"SourcePath" = "8:..\\samples\\resources\\hscrollshmupsprites.bin"
"TargetName" = "8:hscrollshmupsprites.bin"
"Tag" = "8:"
"Folder" = "8:_758C6547998745659548D0656D380FEA"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_539501D7FC4941B8AEE943A2D5C74703"
{
"SourcePath" = "8:..\\samples\\games\\snake.c"
@ -1961,6 +1909,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_652D33F4F54F4974AA6C4CD23A323FD1"
{
"SourcePath" = "8:..\\samples\\resources\\hscrollshmuptiles.bin"
"TargetName" = "8:hscrollshmuptiles.bin"
"Tag" = "8:"
"Folder" = "8:_758C6547998745659548D0656D380FEA"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_67C8F824E02B4211B315AB32AB7ABBB1"
{
"SourcePath" = "8:..\\samples\\games\\breakout.c"
@ -2081,12 +2049,12 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_749A2BA18335F50EB53CCE7029861FBC"
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7393641DDDD742BCA845F192181E1294"
{
"SourcePath" = "8:api-ms-win-crt-runtime-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-runtime-l1-1-0.dll"
"SourcePath" = "8:..\\samples\\games\\hscrollshmup.c"
"TargetName" = "8:hscrollshmup.c"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Folder" = "8:_BC04C0DDE264410096618981E4E890DA"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
@ -2098,7 +2066,7 @@
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_749F54DFBD4D404DA9C2E2D5BA7CDDBF"
@ -2281,12 +2249,12 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8667075410229C38BF63AC1CC776055E"
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_814F6BFC9788449DB259F99386D39AFD"
{
"SourcePath" = "8:api-ms-win-crt-filesystem-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-filesystem-l1-1-0.dll"
"SourcePath" = "8:..\\include\\audio\\sidfx.c"
"TargetName" = "8:sidfx.c"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Folder" = "8:_A4C8078BC7A74CCABB1050E80BC79950"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
@ -2298,7 +2266,7 @@
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8827B6B07A1C4B32B08DF784E090381D"
@ -2841,6 +2809,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B59AF91A39B749DF9E6B95CD35C5C6AC"
{
"SourcePath" = "8:..\\samples\\resources\\hscrollshmupmap.bin"
"TargetName" = "8:hscrollshmupmap.bin"
"Tag" = "8:"
"Folder" = "8:_758C6547998745659548D0656D380FEA"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B85448D515F0487FB6845119AE346F1D"
{
"SourcePath" = "8:..\\samples\\resources\\landersprites.bin"
@ -3201,6 +3189,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D2CCF52F2336415EAD896A2C5410D5E8"
{
"SourcePath" = "8:..\\samples\\resources\\hscrollshmupchars.bin"
"TargetName" = "8:hscrollshmupchars.bin"
"Tag" = "8:"
"Folder" = "8:_758C6547998745659548D0656D380FEA"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D34AB6F4EE6C4E18A8C6D44CC8E23CB7"
{
"SourcePath" = "8:..\\samples\\games\\maze3d.c"
@ -3281,26 +3289,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DD5A4DD822437085CD584319732F2D4D"
{
"SourcePath" = "8:api-ms-win-crt-heap-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-heap-l1-1-0.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DEADBEA270134B77800770802B21859C"
{
"SourcePath" = "8:..\\samples\\games\\connectfour.c"
@ -3501,26 +3489,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EA3C0BCB01F2639DFA2E37EC8436E5F6"
{
"SourcePath" = "8:VERSION.dll"
"TargetName" = "8:VERSION.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED872D39D58443D590B7C80604BC0FF4"
{
"SourcePath" = "8:..\\samples\\kernalio\\fileread.c"
@ -3621,26 +3589,6 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F20F5618C7576D758C01D89C87469AF8"
{
"SourcePath" = "8:api-ms-win-crt-locale-l1-1-0.dll"
"TargetName" = "8:api-ms-win-crt-locale-l1-1-0.dll"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F35970F9D8FA46B09F36D7E9DE5532CA"
{
"SourcePath" = "8:..\\include\\c64\\charwin.h"
@ -3955,6 +3903,17 @@
{
}
}
"{9EF0B969-E518-4E46-987F-47570745A589}:_A4C8078BC7A74CCABB1050E80BC79950"
{
"Name" = "8:audio"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:_D9D33FD9864B40ECADCC2496B1BA18F8"
"Folders"
{
}
}
"{9EF0B969-E518-4E46-987F-47570745A589}:_E0C7A8689A4144D0842BCEDA85A07B5D"
{
"Name" = "8:gfx"
@ -3986,15 +3945,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{45230711-622D-4FA7-BB9C-5357A3B7B1D0}"
"PackageCode" = "8:{5E1C7EF9-3CBE-4341-9696-4E6823EB2A83}"
"ProductCode" = "8:{39622A78-2972-4EF3-9E08-A2E1ECE24245}"
"PackageCode" = "8:{0520CCC0-4961-4AC1-AABA-1471E1EC2D80}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.4.98"
"ProductVersion" = "8:1.4.99"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"

View File

@ -5,4 +5,5 @@
../../bin/oscar64 missile.c -O3 -n
../../bin/oscar64 breakout.c -n
../../bin/oscar64 connectfour.c -n
../../bin/oscar64 hscrollshmup.c -O2 -n

View File

@ -4,29 +4,35 @@
#include <c64/joystick.h>
#include <c64/cia.h>
#include <c64/rasterirq.h>
#include <audio/sidfx.h>
#include <string.h>
#include <stdlib.h>
byte * const Screen = (byte *)0xc800;
byte * const Font = (byte *)0xe000;
byte * const TextFont = (byte *)0xe800;
byte * const Color = (byte *)0xd800;
byte * const Sprites = (byte *)0xd000;
// Character set
char charset[2048] = {
#embed "../../../assets/uridium1 - Chars.bin"
#embed "../resources/hscrollshmupchars.bin"
};
char tcharset[2048] = {
#embed "../resources/breakoutchars.bin"
};
char tileset[] = {
#embed "../../../assets/uridium1 - Tiles.bin"
#embed "../resources/hscrollshmuptiles.bin"
};
char tilemap[128 * 5] = {
#embed "../../../assets/uridium1 - Map (128x5).bin"
#embed "../resources/hscrollshmupmap.bin"
};
char spriteset[4096] = {
#embed 4096 0 "../../../assets/uridium1 - Sprites.bin"
#embed 4096 0 "../resources/hscrollshmupsprites.bin"
};
char xtileset[16][64];
@ -39,7 +45,175 @@ char xcollision[256];
RIRQCode bottom, top;
struct Enemy
{
int px;
byte py;
sbyte dx;
byte state, pad0, pad1, pad2;
} enemies[5];
struct Player
{
int spx;
sbyte vpx;
sbyte ax;
char aphase;
char spy;
char fdelay;
} player;
enum GameState
{
GS_START,
GS_READY, // Getting ready
GS_PLAYING,
GS_EXPLODING,
GS_GAME_OVER
};
struct Game
{
GameState state;
char count;
char edelay;
char ecount;
char escore;
char lives;
} game;
SIDFX SIDFXFire[1] = {{
8000, 1000,
SID_CTRL_GATE | SID_CTRL_SAW,
SID_ATK_16 | SID_DKY_114,
0x40 | SID_DKY_750,
-80, 0,
4, 30
}};
SIDFX SIDFXExplosion[1] = {{
1000, 1000,
SID_CTRL_GATE | SID_CTRL_NOISE,
SID_ATK_2 | SID_DKY_6,
0xf0 | SID_DKY_1500,
-20, 0,
8, 40
}};
SIDFX SIDFXBigExplosion[3] = {
{
1000, 1000,
SID_CTRL_GATE | SID_CTRL_SAW,
SID_ATK_2 | SID_DKY_6,
0xf0 | SID_DKY_168,
-20, 0,
4, 0
},
{
1000, 1000,
SID_CTRL_GATE | SID_CTRL_NOISE,
SID_ATK_2 | SID_DKY_6,
0xf0 | SID_DKY_168,
-20, 0,
10, 0
},
{
1000, 1000,
SID_CTRL_GATE | SID_CTRL_NOISE,
SID_ATK_2 | SID_DKY_6,
0xf0 | SID_DKY_1500,
-10, 0,
8, 80
},
};
// 0123456789012345678901234567890123456789
const char StatusText[] = s" Score: 000000 High: 000000 Lives: 0 ";
// initialize status line
void status_init(void)
{
for(char i=0; i<40; i++)
Screen[i] = StatusText[i];
}
void status_update(void)
{
Screen[38] = game.lives + '0';
// Increment the score from a given digit on
if (game.escore)
{
char at, val = 1;
if (game.escore >= 100)
{
game.escore -= 100;
at = 11;
}
else if (game.escore >= 10)
{
game.escore -= 10;
at = 12;
}
else
{
val = game.escore;
game.escore = 0;
at = 13;
}
// Loop while there is still score to account for
while (val)
{
// Increment one character
char ch = Screen[at] + val;
val = 0;
// Check overflow
if (ch > '9')
{
ch -= 10;
val = 1;
}
Screen[at] = ch;
// Next higher character
at --;
}
}
}
// Reset score and update high score
void score_reset(void)
{
// Find first digit, where score and highscore differ
char i = 0;
while (i < 6 && Screen[i + 8] == Screen[i + 22])
i++;
// Check if new score is higher
if (i < 6 && Screen[i + 8] > Screen[i + 22])
{
// If so, copy to highscore
while (i < 6)
{
Screen[i + 22] = Screen[i + 8];
i++;
}
}
// Clear score
for(char i=0; i<6; i++)
Screen[i + 8] = '0';
}
// unpack tiles into a fast accessible format
void tiles_unpack(void)
{
for(char t=0; t<64; t++)
@ -255,9 +429,9 @@ inline void shot_draw(char * dp, char i, char xp, char yp)
fdp[yp] = 0x00;
}
void shot_add(int dx, int sy)
void shot_add(int sx, char sy, sbyte dx)
{
char py = sy - 6;
char py = sy - 14;
char gy = py >> 5;
char ey = (py >> 3) & 3;
char ry = py & 7;
@ -273,17 +447,17 @@ void shot_add(int dx, int sy)
s->ty = gy;
s->ry = ry;
s->dx = dx;
if (dx < 0)
{
s->dx = -1;
char x = (148 - 4 * dx) >> 3;
char x = (sx) >> 3;
s->n = x - 1;
s->x = 40 * ey + x;
}
else
{
s->dx = 1;
char x = (156 - 4 * dx) >> 3;
char x = (sx + 24) >> 3;
s->x = 40 * ey + x;
s->n = 39 - x;
}
@ -291,10 +465,16 @@ void shot_add(int dx, int sy)
void tiles_draw(unsigned x)
{
// vic.color_border++;
vic_waitTop();
while (vic.raster < 106)
;
// vic.color_border--;
char xs = 7 - (x & 7);
rirq_data(&top, 0, VIC_CTRL2_MCM | xs);
rirq_data(&top, 1, ~(1 << xs));
rirq_data(&top, 1, VIC_CTRL2_MCM | xs);
rirq_data(&top, 2, ~(1 << xs));
x >>= 3;
@ -306,8 +486,8 @@ void tiles_draw(unsigned x)
for(int iy=0; iy<5; iy++)
{
char * dp = Screen + 80 + 160 * iy;
char * cp = Color + 80 + 160 * iy;
char * dp = Screen + 120 + 160 * iy;
char * cp = Color + 120 + 160 * iy;
char * tp = xtilemap + xl + 144 * iy;
switch (xr)
@ -387,21 +567,95 @@ void tiles_draw(unsigned x)
}
struct Enemy
void player_init(void)
{
int px;
byte py;
sbyte dx;
byte state, pad0, pad1, pad2;
} enemies[5];
player.vpx = 0;
player.ax = 1;
player.spy = 100;
player.fdelay = 0;
int spx = 40;
sbyte vpx = 16;
sbyte ax = 0;
char spy = 100;
char fdelay = 0;
char edelay = 5;
char ecount = 0;
spr_set(0, true, 160, 100, 64, VCOL_BLUE, true, false, false);
spr_set(7, true, 160, 100, 64 + 16, VCOL_MED_GREY, true, false, false);
vic.spr_priority = 0x80;
}
void player_control(void)
{
joy_poll(0);
if (joyx[0] != 0)
player.ax = joyx[0];
player.spy += 2 * joyy[0];
if (player.spy < 14)
player.spy = 14;
else if (player.spy > 14 + 159)
player.spy = 14 + 159;
if (player.ax > 0)
{
if (player.vpx < 32)
player.vpx++;
if (player.aphase > 0 && player.aphase < 16)
player.aphase--;
else if (player.aphase >= 16 && player.aphase < 32)
player.aphase++;
}
else if (player.ax < 0)
{
if (player.vpx > - 32)
player.vpx--;
if (player.aphase >= 0 && player.aphase < 16)
player.aphase++;
else if (player.aphase > 16 && player.aphase < 32)
player.aphase--;
}
player.aphase &= 31;
spr_image(0, 64 + (player.aphase >> 1));
spr_image(7, 80 + (player.aphase >> 1));
int px = 148 - 4 * player.vpx;
if (player.fdelay)
player.fdelay--;
else if (joyb[0])
{
if (player.aphase < 4 || player.aphase >= 29)
{
shot_add(px, player.spy, 1);
sidfx_play(0, SIDFXFire, 1);
}
else if (player.aphase >= 13 && player.aphase < 20)
{
shot_add(px, player.spy, -1);
sidfx_play(0, SIDFXFire, 1);
}
player.fdelay = 6;
}
spr_move(0, 24 + px, 50 + player.spy);
spr_move(7, 32 + px, 58 + player.spy);
}
void player_move()
{
player.spx += player.vpx >> 2;
}
void game_init(void)
{
game.edelay = 80;
game.ecount = 0;
game.escore = 0;
game.lives = 4;
player.spx = 40;
}
void enemies_move(void)
{
@ -411,11 +665,11 @@ void enemies_move(void)
{
enemies[i].px += enemies[i].dx;
int rx = enemies[i].px - spx;
int rx = enemies[i].px - player.spx;
if (rx < -192 || rx >= 480)
{
enemies[i].state = 0;
ecount--;
game.ecount--;
spr_show(2 + i, false);
}
else
@ -428,12 +682,13 @@ void enemies_move(void)
}
else
{
spr_color(2 + i, VCOL_YELLOW);
spr_image(2 + i, 127 - (enemies[i].state >> 2));
enemies[i].state--;
if (enemies[i].state == 0)
{
spr_show(2 + i, false);
ecount--;
game.ecount--;
}
}
}
@ -445,31 +700,63 @@ void enemies_spawn(void)
{
char u = rand();
char e = ecount;
char e = game.ecount;
__assume(e < 5);
sbyte v = 1 + (u & 3);
enemies[ecount].py = 21 + 32 * e;
enemies[ecount].dx = vpx < 0 ? v : -v;
enemies[ecount].px = (vpx < 0 ? spx - 56 : spx + 320) + ((u >> 1) & 31);
enemies[ecount].state = 0x80;
enemies[e].py = 29 + 32 * e;
enemies[e].dx = player.vpx < 0 ? v : -v;
enemies[e].px = (player.vpx < 0 ? player.spx - 56 : player.spx + 320) + ((u >> 1) & 31);
enemies[e].state = 0x80;
int rx = enemies[ecount].px - spx;
int rx = enemies[e].px - player.spx;
spr_set(2 + ecount, true, rx + 24, enemies[ecount].py + 50, vpx < 0 ? 97 : 96, VCOL_YELLOW, true, false, false);
ecount++;
spr_set(2 + e, true, rx + 24, enemies[e].py + 50, player.vpx < 0 ? 97 : 96, VCOL_LT_BLUE, true, false, false);
game.ecount++;
}
void shots_check(void)
void enemies_reset(void)
{
for(char i=0; i<5; i++)
{
spr_show(2 + i, false);
enemies[i].state = 0x00;
}
game.edelay = 80;
game.ecount = 0;
}
bool player_check(void)
{
char e = (player.spy - 14) >> 5;
if (e < 5 && (enemies[e].state & 0x80))
{
int rx = enemies[e].px - player.spx;
rx -= 148 - 4 * player.vpx;
if (rx >= - 12 && rx <= 12)
{
enemies[e].state = 64;
return true;
}
}
return false;
}
bool shots_check(void)
{
Shot * ps = shots;
bool hit = false;
for(char i=0; i<5; i++)
{
if (enemies[i].state & 0x80)
{
sbyte rx = (enemies[i].px - spx) >> 3;
sbyte rx = (enemies[i].px - player.spx) >> 3;
if (rx >= 0 && rx < 40)
{
Shot * ss = ps->next;
@ -487,6 +774,8 @@ void shots_check(void)
ss->next = freeShot;
freeShot = ss;
enemies[i].state = 64;
game.escore++;
hit = true;
break;
}
@ -496,8 +785,114 @@ void shots_check(void)
}
}
}
return hit;
}
void game_state(GameState state)
{
// Set new state
game.state = state;
switch (state)
{
case GS_START:
game_init();
game_state(GS_READY);
break;
case GS_READY:
game.count = 120;
spr_show(0, false);
spr_show(7, false);
break;
case GS_PLAYING:
player_init();
break;
case GS_EXPLODING:
sidfx_play(0, SIDFXBigExplosion, 3);
spr_color(0, 7);
spr_color(7, 8);
game.count = 64;
break;
case GS_GAME_OVER:
score_reset();
game.count = 120;
break;
}
}
void game_loop()
{
tiles_draw(player.spx & 4095);
switch (game.state)
{
case GS_START:
break;
case GS_READY:
player.spx -= game.count >> 2;
if (!--game.count)
game_state(GS_PLAYING);
break;
case GS_PLAYING:
player_control();
player_move();
if (game.edelay)
{
game.edelay--;
if (game.edelay < 10 && !(game.edelay & 1))
enemies_spawn();
}
else
{
enemies_move();
if (!game.ecount)
game.edelay = 64 + (rand() & 63);
}
if (shots_check())
sidfx_play(1, SIDFXExplosion, 1);
if (player_check())
game_state(GS_EXPLODING);
break;
case GS_EXPLODING:
spr_image(0, 127 - (game.count >> 2));
spr_image(7, 127 - (game.count >> 2));
player_move();
enemies_move();
if (!--game.count)
{
enemies_reset();
game.lives--;
if (game.lives)
game_state(GS_READY);
else
game_state(GS_GAME_OVER);
}
break;
case GS_GAME_OVER:
if (!--game.count)
game_state(GS_START);
break;
}
// vic.color_border--;
sidfx_loop();
// vic.color_border++;
status_update();
}
int main(void)
{
cia_init();
@ -507,6 +902,7 @@ int main(void)
// Install character set
mmap_set(MMAP_RAM);
memcpy(Font, charset, 2048);
memcpy(TextFont, tcharset, 2048);
char * dp = Font + 248 * 8;
memset(dp, 0xff, 8);
@ -514,6 +910,7 @@ int main(void)
memcpy(Sprites, spriteset, 4096);
mmap_set(MMAP_NO_ROM);
// bring tiles into better addressed format
tiles_unpack();
// Switch screen
@ -525,14 +922,18 @@ int main(void)
rirq_init(true);
// Set scroll offset and star at top of screen
rirq_build(&top, 2);
rirq_write(&top, 0, &vic.ctrl2, VIC_CTRL2_MCM);
rirq_write(&top, 1, Font + 248 * 8 + 2, 0xff);
rirq_build(&top, 4);
rirq_write(&top, 0, &vic.memptr, (((unsigned)Screen >> 6) & 0xf0) | (((unsigned)Font >> 10) & 0x0e));
rirq_write(&top, 1, &vic.ctrl2, VIC_CTRL2_MCM);
rirq_write(&top, 2, Font + 248 * 8 + 2, 0xff);
rirq_write(&top, 3, &vic.color_back, VCOL_WHITE);
rirq_set(0, 58, &top);
// Switch to text mode for status line and poll joystick at bottom
rirq_build(&bottom, 1);
rirq_write(&bottom, 0, &vic.ctrl2, VIC_CTRL2_MCM | VIC_CTRL2_CSEL);
rirq_build(&bottom, 3);
rirq_write(&bottom, 0, &vic.memptr, (((unsigned)Screen >> 6) & 0xf0) | (((unsigned)TextFont >> 10) & 0x0e));
rirq_write(&bottom, 1, &vic.ctrl2, 0);
rirq_write(&bottom, 2, &vic.color_back, VCOL_YELLOW);
rirq_set(1, 250, &bottom);
// sort the raster IRQs
@ -550,105 +951,31 @@ int main(void)
vic.spr_mcolor0 = VCOL_DARK_GREY;
vic.spr_mcolor1 = VCOL_WHITE;
// clear screen
memset(Screen, 0, 1000);
memset(Color, 8, 1000);
memset(Color, 0, 80);
memset(Color + 80, 8, 920);
sidfx_init();
sid.fmodevol = 15;
status_init();
// initialize background parallax stars
for(int i=0; i<24; i++)
stars[i] = rand() % 40 + 40 * (i & 3);
shot_init();
spr_set(0, true, 160, 100, 64, VCOL_BLUE, true, false, false);
spr_set(7, true, 160, 100, 64 + 16, VCOL_MED_GREY, true, false, false);
vic.spr_priority = 0x80;
game_init();
player_init();
vpx = 2;
// main game loop
game_state(GS_READY);
for(;;)
{
joy_poll(0);
if (ax == 0)
ax = joyx[0];
spy += 2 * joyy[0];
if (spy < 6)
spy = 6;
else if (spy > 6 + 159)
spy = 6 + 159;
if (ax > 0)
{
if (vpx < 32)
vpx++;
else
ax = 0;
if (vpx >= 32)
{
spr_image(0, 64);
spr_image(7, 64 + 16);
}
else
{
spr_image(0, 76 + (vpx >> 3));
spr_image(7, 76 + (vpx >> 3) + 16);
}
}
else if (ax < 0)
{
if (vpx > - 32)
vpx--;
else
ax = 0;
if (vpx <= -32)
{
spr_image(0, 72);
spr_image(7, 72 + 16);
}
else
{
spr_image(0, 68 - (vpx >> 3));
spr_image(7, 68 - (vpx >> 3) + 16);
}
}
if (fdelay)
fdelay--;
else if (joyb[0] && vpx != 0)
{
shot_add(vpx, spy);
fdelay = 6;
}
spr_move(0, 172 - 4 * vpx, 50 + spy);
spr_move(7, 180 - 4 * vpx, 58 + spy);
vic.color_border = VCOL_BLACK;
vic_waitTop();
while (vic.raster < 82)
;
vic.color_border = VCOL_BLUE;
tiles_draw(spx & 4095);
vic.color_border = VCOL_WHITE;
if (edelay)
{
edelay--;
if (edelay < 10 && !(edelay & 1))
enemies_spawn();
}
else
{
enemies_move();
if (!ecount)
edelay = 64 + (rand() & 63);
}
shots_check();
spx += vpx >> 2;
game_loop();
}
return 0;

View File

@ -4,3 +4,4 @@ call ..\..\bin\oscar64 -n maze3d.c
call ..\..\bin\oscar64 -n -O3 missile.c
call ..\..\bin\oscar64 -n breakout.c
call ..\..\bin\oscar64 -n connectfour.c
call ..\..\bin\oscar64 -n -O2 hscrollshmup.c

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -38,7 +38,7 @@ int main(void)
{
// calculate sine table
for(int i=0; i<128; i++)
sintab[i] = (int)(80 * sin(i * PI / 64));
sintab[i] = (int)(70 * sin(i * PI / 64));
// enable raster interrupt via kernal path
rirq_init(true);
@ -68,7 +68,7 @@ int main(void)
char k = j >> 4;
for(char i=0; i<16; i++)
{
vspr_move(i, 200 + sintab[(j + 8 * i) & 127] + sintab[k & 127], 140 + sintab[(j + 8 * i + 32) & 127] + sintab[(k + 32) & 127]);
vspr_move(i, 200 + sintab[(j + 8 * i) & 127] + sintab[k & 127], 150 + sintab[(j + 8 * i + 32) & 127] + sintab[(k + 32) & 127]);
}
j++;