Add __hwinterrupt function decoration
This commit is contained in:
parent
5147ec6bc9
commit
d4352ef043
83
README.md
83
README.md
|
@ -177,63 +177,44 @@ Labels are defined with a colon after the name. Pure assembler functions can be
|
|||
|
||||
### Interrupt routines
|
||||
|
||||
The C compiler will not generate good interrupt code, it is simply too greedy with the zero page registers. Interrupt code should therefore be written in assembler.
|
||||
The compiler provides two levels of interrupt safe functions. The specifier __interrupt caues all zero page registers used by the function to be saved, the __hwinterrupt also saves the CPU registers and exits the function with rti
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <c64/memmap.h>
|
||||
#include <c64/cia.h>
|
||||
#include <c64/vic.h>
|
||||
|
||||
// Next line for interrupt
|
||||
volatile char npos;
|
||||
__hwinterrupt void irq(void)
|
||||
{
|
||||
vic.color_border++;
|
||||
|
||||
// Interrupt routine
|
||||
__asm irq
|
||||
{
|
||||
lda $d019 // Check if it is raster IRQ
|
||||
and #$01
|
||||
beq w1
|
||||
|
||||
inc $d020 // Start colored section
|
||||
inc $d021
|
||||
|
||||
ldx #20 // Wait for 2/3 lines
|
||||
l1: dex
|
||||
bne l1
|
||||
|
||||
dec $d020 // End colored section
|
||||
dec $d021
|
||||
|
||||
lda npos // Setup next interrupt
|
||||
sta $d012
|
||||
w1:
|
||||
asl $d019 // Ack interrupt
|
||||
|
||||
jmp $ea31 // System IRQ routine
|
||||
}
|
||||
// some interrupt code
|
||||
|
||||
int main(void)
|
||||
{
|
||||
__asm { sei } // Disable interrupt
|
||||
|
||||
|
||||
*(void **)0x0314 = irq; // Install interrupt routine
|
||||
*(char *)0xd01a = 1; // Enable raster interrupt
|
||||
*(char *)0xd011 &= 0x7f; // Set raster line for IRQ
|
||||
*(char *)0xd012 = 100;
|
||||
vic.color_border--;
|
||||
vic.intr_ctrl <<= 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
__asm { sei } // Disable interrupt
|
||||
mmap_set(MMAP_NO_ROM); // Disable kernal rom
|
||||
cia_init(); // No more CIA interrupts
|
||||
|
||||
*(void **)0xfffe = irq; // Install interrupt routine
|
||||
vic.intr_enable = VIC_INTR_RST; // Init raster interrupt
|
||||
vic.ctrl1 &= ~VIC_CTRL1_RST8;
|
||||
vic.raster = 100;
|
||||
|
||||
__asm { cli } // Re-enable interrupt
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Non interrupt code
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
npos = 100;
|
||||
|
||||
__asm { cli } // Re-enable interrupt
|
||||
|
||||
// Move the interrupt raster line up/down
|
||||
float f = 0;
|
||||
while (true)
|
||||
{
|
||||
npos = 130 + (int)(100 * sin(f));
|
||||
f += 0.1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
## Implementation Details
|
||||
|
||||
|
|
|
@ -16,4 +16,7 @@ void cia_init(void)
|
|||
|
||||
cia2.prb = 0x07;
|
||||
cia2.ddra = 0x3f;
|
||||
|
||||
char i0 = cia1.icr;
|
||||
char i1 = cia2.icr;
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
struct CIA
|
||||
{
|
||||
volatile byte pra, prb;
|
||||
byte ddra, ddrb;
|
||||
word ta, tb;
|
||||
byte todt, tods, todm, todh;
|
||||
byte sdr;
|
||||
byte icr;
|
||||
byte cra, crb;
|
||||
volatile byte ddra, ddrb;
|
||||
volatile word ta, tb;
|
||||
volatile byte todt, tods, todm, todh;
|
||||
volatile byte sdr;
|
||||
volatile byte icr;
|
||||
volatile byte cra, crb;
|
||||
};
|
||||
|
||||
#define cia1 (*((struct CIA *)0xdc00))
|
||||
|
|
|
@ -48,34 +48,35 @@ enum DecType
|
|||
|
||||
// TypeFlags
|
||||
|
||||
static const uint32 DTF_SIGNED = 0x00000001;
|
||||
static const uint32 DTF_DEFINED = 0x00000002;
|
||||
static const uint32 DTF_GLOBAL = 0x00000004;
|
||||
static const uint32 DTF_VARIADIC = 0x00000008;
|
||||
static const uint32 DTF_INTRINSIC = 0x00000010;
|
||||
static const uint32 DTF_STATIC = 0x00000020;
|
||||
static const uint32 DTF_CONST = 0x00000040;
|
||||
static const uint32 DTF_VOLATILE = 0x00000080;
|
||||
static const uint32 DTF_EXTERN = 0x00000100;
|
||||
static const uint32 DTF_NATIVE = 0x00000200;
|
||||
static const uint32 DTF_UPPER_BYTE = 0x00000400;
|
||||
static const uint32 DTF_LOWER_BYTE = 0x00000800;
|
||||
static const uint32 DTF_SECTION_START = 0x00001000;
|
||||
static const uint32 DTF_SECTION_END = 0x00002000;
|
||||
static const uint32 DTF_FASTCALL = 0x00004000;
|
||||
static const uint32 DTF_INLINE = 0x00008000;
|
||||
static const uint32 DTF_ANALYZED = 0x00010000;
|
||||
static const uint32 DTF_REQUEST_INLINE = 0x00020000;
|
||||
static const uint32 DTF_INTERRUPT = 0x00040000;
|
||||
static const uint32 DTF_EXPORT = 0x00080000;
|
||||
static const uint64 DTF_SIGNED = (1ULL << 0);
|
||||
static const uint64 DTF_DEFINED = (1ULL << 1);
|
||||
static const uint64 DTF_GLOBAL = (1ULL << 2);
|
||||
static const uint64 DTF_VARIADIC = (1ULL << 3);
|
||||
static const uint64 DTF_INTRINSIC = (1ULL << 4);
|
||||
static const uint64 DTF_STATIC = (1ULL << 5);
|
||||
static const uint64 DTF_CONST = (1ULL << 6);
|
||||
static const uint64 DTF_VOLATILE = (1ULL << 7);
|
||||
static const uint64 DTF_EXTERN = (1ULL << 8);
|
||||
static const uint64 DTF_NATIVE = (1ULL << 9);
|
||||
static const uint64 DTF_UPPER_BYTE = (1ULL << 10);
|
||||
static const uint64 DTF_LOWER_BYTE = (1ULL << 11);
|
||||
static const uint64 DTF_SECTION_START = (1ULL << 12);
|
||||
static const uint64 DTF_SECTION_END = (1ULL << 13);
|
||||
static const uint64 DTF_FASTCALL = (1ULL << 14);
|
||||
static const uint64 DTF_INLINE = (1ULL << 15);
|
||||
static const uint64 DTF_ANALYZED = (1ULL << 16);
|
||||
static const uint64 DTF_REQUEST_INLINE = (1ULL << 17);
|
||||
static const uint64 DTF_INTERRUPT = (1ULL << 18);
|
||||
static const uint64 DTF_EXPORT = (1ULL << 19);
|
||||
static const uint64 DTF_HWINTERRUPT = (1ULL << 20);
|
||||
|
||||
static const uint32 DTF_FUNC_VARIABLE = 0x00100000;
|
||||
static const uint32 DTF_FUNC_ASSEMBLER = 0x00200000;
|
||||
static const uint32 DTF_FUNC_RECURSIVE = 0x00400000;
|
||||
static const uint32 DTF_FUNC_ANALYZING = 0x00800000;
|
||||
static const uint32 DTF_FUNC_CONSTEXPR = 0x01000000;
|
||||
static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32);
|
||||
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33);
|
||||
static const uint64 DTF_FUNC_RECURSIVE = (1ULL << 34);
|
||||
static const uint64 DTF_FUNC_ANALYZING = (1ULL << 35);
|
||||
static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36);
|
||||
|
||||
static const uint32 DTF_VAR_ALIASING = 0x02000000;
|
||||
static const uint64 DTF_VAR_ALIASING = (1ULL << 37);
|
||||
|
||||
|
||||
class Declaration;
|
||||
|
@ -175,7 +176,7 @@ public:
|
|||
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment;
|
||||
int64 mInteger;
|
||||
double mNumber;
|
||||
uint32 mFlags;
|
||||
uint64 mFlags;
|
||||
const Ident * mIdent;
|
||||
LinkerSection * mSection;
|
||||
const uint8 * mData;
|
||||
|
|
|
@ -2976,7 +2976,9 @@ void InterCodeBasicBlock::CollectEntryBlocks(InterCodeBasicBlock* from)
|
|||
|
||||
void InterCodeBasicBlock::BuildDominatorTree(InterCodeBasicBlock* from)
|
||||
{
|
||||
if (!mDominator)
|
||||
if (from == this)
|
||||
return;
|
||||
else if (!mDominator)
|
||||
mDominator = from;
|
||||
else if (from == mDominator)
|
||||
return;
|
||||
|
@ -7289,6 +7291,9 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
|||
hasCall = true;
|
||||
}
|
||||
|
||||
GrowingArray<InterInstructionPtr> tvalues(nullptr);
|
||||
GrowingArray<int> nassigns(0);
|
||||
|
||||
for (int i = 0; i < mInstructions.Size(); i++)
|
||||
{
|
||||
InterInstruction* ins = mInstructions[i];
|
||||
|
@ -7320,7 +7325,24 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
|||
if (sins->mSrc[1].mTemp >= 0)
|
||||
{
|
||||
if ((ins->mSrc[0].mMemory != IM_PARAM && ins->mSrc[0].mMemory != IM_FPARAM) || aliasedParams[ins->mSrc[0].mVarIndex])
|
||||
ins->mInvariant = false;
|
||||
{
|
||||
int k = j - 1;
|
||||
while (k >= 0 && mInstructions[k]->mDst.mTemp != sins->mSrc[1].mTemp)
|
||||
k--;
|
||||
if (k >= 0)
|
||||
{
|
||||
InterInstruction* lins = mInstructions[k];
|
||||
if (lins->mCode == IC_LEA && lins->mSrc[1].mTemp < 0)
|
||||
{
|
||||
if (ins->mSrc[0].mMemory == lins->mSrc[1].mMemory && ins->mSrc[0].mVarIndex == lins->mSrc[1].mVarIndex && ins->mSrc[0].mLinkerObject == lins->mSrc[1].mLinkerObject)
|
||||
ins->mInvariant = false;
|
||||
}
|
||||
else
|
||||
ins->mInvariant = false;
|
||||
}
|
||||
else
|
||||
ins->mInvariant = false;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[0].mMemory == sins->mSrc[1].mMemory && ins->mSrc[0].mVarIndex == sins->mSrc[1].mVarIndex && ins->mSrc[0].mLinkerObject == sins->mSrc[1].mLinkerObject)
|
||||
{
|
||||
|
@ -7347,7 +7369,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
|||
|
||||
GrowingArray<Dependency> dep(DEP_UNKNOWN);
|
||||
GrowingArray<int64> indexStep(0), indexBase(0);
|
||||
GrowingArray<InterInstructionPtr> tvalues(nullptr);
|
||||
tvalues.SetSize(0);
|
||||
|
||||
for (int i = 0; i < mInstructions.Size(); i++)
|
||||
{
|
||||
|
|
|
@ -476,7 +476,7 @@ public:
|
|||
GrowingTypeArray mTemporaries;
|
||||
GrowingIntArray mTempOffset, mTempSizes;
|
||||
int mTempSize, mCommonFrameSize, mCallerSavedTemps;
|
||||
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure, mInterrupt;
|
||||
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure, mInterrupt, mHardwareInterrupt;
|
||||
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
||||
|
||||
InterCodeModule * mModule;
|
||||
|
|
|
@ -3425,6 +3425,9 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
|
|||
if (dec->mFlags & DTF_INTERRUPT)
|
||||
proc->mInterrupt = true;
|
||||
|
||||
if (dec->mFlags & DTF_HWINTERRUPT)
|
||||
proc->mHardwareInterrupt = true;
|
||||
|
||||
if (dec->mBase->mFlags & DTF_FASTCALL)
|
||||
{
|
||||
proc->mFastCallProcedure = true;
|
||||
|
|
|
@ -13810,9 +13810,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
|||
progress = true;
|
||||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||
(mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR) &&
|
||||
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
|
||||
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
|
||||
mIns[i + 1].IsShift() &&
|
||||
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
|
||||
{
|
||||
mIns[i + 2].mType = mIns[i + 1].mType;
|
||||
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
||||
|
@ -15728,6 +15728,15 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal);
|
||||
zpLocal |= zpGlobal;
|
||||
|
||||
if (proc->mHardwareInterrupt)
|
||||
{
|
||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA));
|
||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_TXA));
|
||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA));
|
||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_TYA));
|
||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA));
|
||||
}
|
||||
|
||||
for (int i = 2; i < 256; i++)
|
||||
{
|
||||
if (zpLocal[i])
|
||||
|
@ -15745,6 +15754,15 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (proc->mHardwareInterrupt)
|
||||
{
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_PLA));
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_TAY));
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_PLA));
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_TAX));
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_PLA));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -15959,7 +15977,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
proc->mLinkerObject->mZeroPageSet = zpLocal;
|
||||
}
|
||||
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
|
||||
if (proc->mHardwareInterrupt)
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTI, ASMIM_IMPLIED));
|
||||
else
|
||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
|
||||
|
||||
mEntryBlock->Assemble();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Parser::~Parser(void)
|
|||
|
||||
}
|
||||
|
||||
Declaration* Parser::ParseStructDeclaration(uint32 flags, DecType dt)
|
||||
Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||
{
|
||||
const Ident* structName = nullptr;
|
||||
|
||||
|
@ -121,7 +121,7 @@ Declaration* Parser::ParseStructDeclaration(uint32 flags, DecType dt)
|
|||
return dec;
|
||||
}
|
||||
|
||||
Declaration* Parser::ParseBaseTypeDeclaration(uint32 flags)
|
||||
Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags)
|
||||
{
|
||||
Declaration* dec = nullptr;
|
||||
|
||||
|
@ -905,7 +905,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
|
|||
Declaration* Parser::ParseDeclaration(bool variable)
|
||||
{
|
||||
bool definingType = false;
|
||||
uint32 storageFlags = 0, typeFlags = 0;
|
||||
uint64 storageFlags = 0, typeFlags = 0;
|
||||
|
||||
if (mScanner->mToken == TK_TYPEDEF)
|
||||
{
|
||||
|
@ -952,6 +952,11 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
|||
storageFlags |= DTF_INTERRUPT | DTF_NATIVE;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else if (mScanner->mToken == TK_HWINTERRUPT)
|
||||
{
|
||||
storageFlags |= DTF_INTERRUPT | DTF_HWINTERRUPT | DTF_NATIVE;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
@ -1028,7 +1033,7 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
|||
{
|
||||
if (!ndec->mBase->IsSame(pdec->mBase))
|
||||
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent->mString);
|
||||
else if (ndec->mFlags & ~pdec->mFlags & (DTF_FASTCALL | DTF_NATIVE))
|
||||
else if (ndec->mFlags & ~pdec->mFlags & (DTF_HWINTERRUPT | DTF_INTERRUPT | DTF_FASTCALL | DTF_NATIVE))
|
||||
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function call type declaration differs", ndec->mIdent->mString);
|
||||
else
|
||||
{
|
||||
|
|
|
@ -27,9 +27,9 @@ protected:
|
|||
|
||||
void ParsePragma(void);
|
||||
|
||||
Declaration* ParseBaseTypeDeclaration(uint32 flags);
|
||||
Declaration* ParseBaseTypeDeclaration(uint64 flags);
|
||||
Declaration* ParseDeclaration(bool variable);
|
||||
Declaration* ParseStructDeclaration(uint32 flags, DecType dt);
|
||||
Declaration* ParseStructDeclaration(uint64 flags, DecType dt);
|
||||
|
||||
Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp);
|
||||
Expression* ParseInitExpression(Declaration* dtype);
|
||||
|
|
|
@ -51,6 +51,7 @@ const char* TokenNames[] =
|
|||
|
||||
"__asm",
|
||||
"__interrupt",
|
||||
"__hwinterrupt",
|
||||
"__native",
|
||||
"__fastcall",
|
||||
"__export",
|
||||
|
@ -1304,6 +1305,8 @@ void Scanner::NextRawToken(void)
|
|||
mToken = TK_ASSUME;
|
||||
else if (!strcmp(tkident, "__interrupt"))
|
||||
mToken = TK_INTERRUPT;
|
||||
else if (!strcmp(tkident, "__hwinterrupt"))
|
||||
mToken = TK_HWINTERRUPT;
|
||||
else if (!strcmp(tkident, "__native"))
|
||||
mToken = TK_NATIVE;
|
||||
else if (!strcmp(tkident, "__fastcall"))
|
||||
|
|
|
@ -49,6 +49,7 @@ enum Token
|
|||
|
||||
TK_ASM,
|
||||
TK_INTERRUPT,
|
||||
TK_HWINTERRUPT,
|
||||
TK_NATIVE,
|
||||
TK_FASTCALL,
|
||||
TK_EXPORT,
|
||||
|
|
|
@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
|
|||
|
||||
#else
|
||||
strcpy(strProductName, "oscar64");
|
||||
strcpy(strProductVersion, "1.4.82");
|
||||
strcpy(strProductVersion, "1.4.83");
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint32_t length = sizeof(basePath);
|
||||
|
@ -245,18 +245,22 @@ int main2(int argc, const char** argv)
|
|||
int main(int argc, const char** argv)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifndef _DEBUG
|
||||
__try
|
||||
{
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return main2(argc, argv);
|
||||
|
||||
#ifdef _WIN32
|
||||
}
|
||||
#ifndef _DEBUG
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
printf("oscar64 crashed.");
|
||||
return 30;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,4,82,0
|
||||
PRODUCTVERSION 1,4,82,0
|
||||
FILEVERSION 1,4,83,0
|
||||
PRODUCTVERSION 1,4,83,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,12 +43,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "oscar64"
|
||||
VALUE "FileDescription", "oscar64 compiler"
|
||||
VALUE "FileVersion", "1.4.82.0"
|
||||
VALUE "FileVersion", "1.4.83.0"
|
||||
VALUE "InternalName", "oscar64.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||
VALUE "OriginalFilename", "oscar64.exe"
|
||||
VALUE "ProductName", "oscar64"
|
||||
VALUE "ProductVersion", "1.4.82.0"
|
||||
VALUE "ProductVersion", "1.4.83.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -3648,15 +3648,15 @@
|
|||
{
|
||||
"Name" = "8:Microsoft Visual Studio"
|
||||
"ProductName" = "8:oscar64"
|
||||
"ProductCode" = "8:{D7EEA6AF-54FD-48A9-80AF-F19CA9A32D0E}"
|
||||
"PackageCode" = "8:{497B8392-6DB9-4695-A4BC-E7E7CA9DCB8E}"
|
||||
"ProductCode" = "8:{273BF824-E947-4B58-8992-6060F95D9EF7}"
|
||||
"PackageCode" = "8:{3C6231C2-746F-4D40-83F7-159286D6BDB3}"
|
||||
"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.82"
|
||||
"ProductVersion" = "8:1.4.83"
|
||||
"Manufacturer" = "8:oscar64"
|
||||
"ARPHELPTELEPHONE" = "8:"
|
||||
"ARPHELPLINK" = "8:"
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue