Add __hwinterrupt function decoration
This commit is contained in:
parent
5147ec6bc9
commit
d4352ef043
57
README.md
57
README.md
|
@ -177,64 +177,45 @@ 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;
|
||||
|
||||
// Interrupt routine
|
||||
__asm irq
|
||||
__hwinterrupt void irq(void)
|
||||
{
|
||||
lda $d019 // Check if it is raster IRQ
|
||||
and #$01
|
||||
beq w1
|
||||
vic.color_border++;
|
||||
|
||||
inc $d020 // Start colored section
|
||||
inc $d021
|
||||
// some interrupt code
|
||||
|
||||
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
|
||||
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 **)0x0314 = irq; // Install interrupt routine
|
||||
*(char *)0xd01a = 1; // Enable raster interrupt
|
||||
*(char *)0xd011 &= 0x7f; // Set raster line for IRQ
|
||||
*(char *)0xd012 = 100;
|
||||
|
||||
npos = 100;
|
||||
*(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
|
||||
|
||||
// Move the interrupt raster line up/down
|
||||
float f = 0;
|
||||
while (true)
|
||||
for(;;)
|
||||
{
|
||||
npos = 130 + (int)(100 * sin(f));
|
||||
f += 0.1;
|
||||
// Non interrupt code
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
## Implementation Details
|
||||
|
||||
The compiler does a full program compile, the linker step is part of the compilation. It knows all functions during the compilation run and includes only reachable code in the output. Source files are added to the build with the help of a pragma:
|
||||
|
|
|
@ -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,8 +7325,25 @@ 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])
|
||||
{
|
||||
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)
|
||||
{
|
||||
ins->mInvariant = false;
|
||||
|
@ -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,6 +15977,9 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
proc->mLinkerObject->mZeroPageSet = zpLocal;
|
||||
}
|
||||
|
||||
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,13 +245,16 @@ 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)
|
||||
{
|
||||
|
@ -259,4 +262,5 @@ int main(int argc, const char** argv)
|
|||
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