diff --git a/include/audio/sidfx.c b/include/audio/sidfx.c index 96fe99a..17ed27f 100644 --- a/include/audio/sidfx.c +++ b/include/audio/sidfx.c @@ -30,13 +30,16 @@ void sidfx_init(void) 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; + if (!channels[chn].com || channels[chn].com->priority <= fx->priority) + { + 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; + channels[chn].com = fx; + channels[chn].cnt = cnt - 1; + } } void sidfx_stop(byte chn) diff --git a/include/audio/sidfx.h b/include/audio/sidfx.h index cfc7627..9bb9733 100644 --- a/include/audio/sidfx.h +++ b/include/audio/sidfx.h @@ -9,6 +9,7 @@ struct SIDFX byte ctrl, attdec, susrel; int dfreq, dpwm; byte time1, time0; + byte priority; }; void sidfx_init(void); diff --git a/include/c64/rasterirq.c b/include/c64/rasterirq.c index f2078a6..29b47c6 100644 --- a/include/c64/rasterirq.c +++ b/include/c64/rasterirq.c @@ -6,6 +6,7 @@ #include volatile char npos = 1, tpos = 0; +volatile byte rirq_count; byte rasterIRQRows[NUM_IRQS]; byte rasterIRQIndex[NUM_IRQS]; @@ -62,6 +63,7 @@ w1: e2: ldx npos stx tpos + inc rirq_count bit $d011 bmi e1 @@ -135,6 +137,7 @@ w1: e2: ldx npos stx tpos + inc rirq_count bit $d011 bmi e1 diff --git a/include/c64/rasterirq.h b/include/c64/rasterirq.h index f47cc5d..d401580 100644 --- a/include/c64/rasterirq.h +++ b/include/c64/rasterirq.h @@ -5,6 +5,7 @@ #define NUM_IRQS 16 +extern volatile byte rirq_count; enum RIRQCodeIndex { diff --git a/include/oscar.c b/include/oscar.c new file mode 100644 index 0000000..ea3acba --- /dev/null +++ b/include/oscar.c @@ -0,0 +1,88 @@ +#include "oscar.h" + +const char * oscar_expand_lzo(char * dp, const char * sp) +{ + char cmd = sp[0]; + do + { + const char * cp; + + if (cmd & 0x80) + { + cp = dp - sp[1]; + cmd &= 0x7f; + sp += 2; + } + else + { + sp += 1; + cp = sp; + sp += cmd; + } + + char n = 0x00; + do { + dp[n] = cp[n]; + n++; + } while (n != cmd); + dp += cmd; + + cmd = sp[0]; + } while (cmd); + + return sp + 1; +} + +const char * oscar_expand_rle(char * dp, const char * sp) +{ + char cmd = sp[0]; + + do + { + if (cmd & 0x80) + { + char rep = (cmd & 0x70) >> 4; + char c = sp[1]; + for(signed char i=rep; i>=0; i--) + dp[i] = c; + + rep++; + sp += 2; + dp += rep; + + cmd &= 0x0f; + for(signed char i=cmd; i>=0; i--) + dp[i] = sp[i]; + + cmd++; + sp += cmd; + dp += cmd; + } + else if (cmd & 0x40) + { + cmd &= 0x3f; + sp ++; + for(signed char i=cmd; i>=0; i--) + dp[i] = sp[i]; + + cmd++; + sp += cmd; + dp += cmd; + } + else + { + char c = sp[1]; + for(signed char i=cmd; i>=0; i--) + dp[i] = c; + + cmd++; + sp += 2; + dp += cmd; + } + + cmd = sp[0]; + + } while (cmd) + + return sp + 1; +} diff --git a/include/oscar.h b/include/oscar.h new file mode 100644 index 0000000..590867d --- /dev/null +++ b/include/oscar.h @@ -0,0 +1,12 @@ +#ifndef OSCAR_H +#define OSCAR_H + + +__native const char * oscar_expand_lzo(char * dp, const char * sp); + +__native const char * oscar_expand_rle(char * dp, const char * sp); + + +#pragma compile("oscar.c") + +#endif diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index f3f0d4e..50ab111 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -21,7 +21,7 @@ static const uint32 LIVE_ALL = 0x000000ff; static int GlobalValueNumber = 0; NativeRegisterData::NativeRegisterData(void) - : mMode(NRDM_UNKNOWN), mValue(GlobalValueNumber++) + : mMode(NRDM_UNKNOWN), mValue(GlobalValueNumber++), mMask(0) { } @@ -32,6 +32,11 @@ void NativeRegisterData::Reset(void) mValue = GlobalValueNumber++; } +void NativeRegisterData::ResetMask(void) +{ + mMask = 0; +} + bool NativeRegisterData::SameData(const NativeRegisterData& d) const { if (mMode != d.mMode) @@ -56,6 +61,14 @@ void NativeRegisterDataSet::Reset(void) mRegs[i].Reset(); } +void NativeRegisterDataSet::ResetMask(void) +{ + for (int i = 0; i < NUM_REGS; i++) + mRegs[i].ResetMask(); +} + + + void NativeRegisterDataSet::ResetZeroPage(int addr) { mRegs[addr].Reset(); @@ -85,6 +98,15 @@ void NativeRegisterDataSet::ResetIndirect(void) } +void NativeRegisterDataSet::IntersectMask(const NativeRegisterDataSet& set) +{ + for (int i = 0; i < NUM_REGS; i++) + { + mRegs[i].mMask &= set.mRegs[i].mMask & ~(mRegs[i].mValue ^ set.mRegs[i].mValue); + } +} + + void NativeRegisterDataSet::Intersect(const NativeRegisterDataSet& set) { @@ -1787,6 +1809,309 @@ void NativeCodeInstruction::Simulate(NativeRegisterDataSet& data) } } +bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmInsType& carryop) +{ + bool changed = false; + + int iaddr = -1; + + if (mMode == ASMIM_IMPLIED) + iaddr = CPU_REG_A; + else if (mMode == ASMIM_ZERO_PAGE) + iaddr = mAddress; + + switch (mType) + { + case ASMIT_JSR: + data.ResetMask(); + break; + case ASMIT_CLC: + data.mRegs[CPU_REG_C].mMask = 1; + data.mRegs[CPU_REG_C].mValue = 0; + break; + case ASMIT_SEC: + data.mRegs[CPU_REG_C].mMask = 1; + data.mRegs[CPU_REG_C].mValue = 1; + break; + + case ASMIT_CMP: + case ASMIT_CPX: + case ASMIT_CPY: + data.mRegs[CPU_REG_C].mMask = 0; + break; + + case ASMIT_ADC: + case ASMIT_SBC: + data.mRegs[CPU_REG_C].mMask = 0; + data.mRegs[CPU_REG_A].mMask = 0; + break; + + case ASMIT_LDA: + if (mMode == ASMIM_ZERO_PAGE) + { + data.mRegs[CPU_REG_A].mMask = data.mRegs[mAddress].mMask; + data.mRegs[CPU_REG_A].mValue = data.mRegs[mAddress].mValue; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) + { + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else if (mMode == ASMIM_IMMEDIATE) + { + data.mRegs[CPU_REG_A].mMask = 0xff; + data.mRegs[CPU_REG_A].mValue = mAddress & 0xff; + } + else + data.mRegs[CPU_REG_A].mMask = 0; + break; + case ASMIT_STA: + if (mMode == ASMIM_ZERO_PAGE) + { + data.mRegs[mAddress].mMask = data.mRegs[CPU_REG_A].mMask; + data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue; + } + break; + + + case ASMIT_AND: + if (mMode == ASMIM_ZERO_PAGE) + { + int zeros = + (data.mRegs[mAddress].mMask & ~data.mRegs[mAddress].mValue) | + (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); + + int ones = + (data.mRegs[mAddress].mMask & data.mRegs[mAddress].mValue) & + (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); + + data.mRegs[CPU_REG_A].mMask = ones | zeros; + data.mRegs[CPU_REG_A].mValue = ones; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) + { + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else if (mMode == ASMIM_IMMEDIATE) + { + int zeros = ~mAddress | (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); + + int ones = mAddress & (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); + + data.mRegs[CPU_REG_A].mMask = ones | zeros; + data.mRegs[CPU_REG_A].mValue = ones; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) + { + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else + data.mRegs[CPU_REG_A].mMask &= ~data.mRegs[CPU_REG_A].mValue; + break; + + case ASMIT_ORA: + if (mMode == ASMIM_ZERO_PAGE) + { + int ones = + (data.mRegs[mAddress].mMask & data.mRegs[mAddress].mValue) | + (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); + + int zeros = + (data.mRegs[mAddress].mMask & ~data.mRegs[mAddress].mValue) & + (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); + + data.mRegs[CPU_REG_A].mMask = ones | zeros; + data.mRegs[CPU_REG_A].mValue = ones; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) + { + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else if (mMode == ASMIM_IMMEDIATE) + { + int ones = mAddress | (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); + + int zeros = ~ mAddress & (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); + + data.mRegs[CPU_REG_A].mMask = ones | zeros; + data.mRegs[CPU_REG_A].mValue = ones; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) + { + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else + data.mRegs[CPU_REG_A].mMask &= data.mRegs[CPU_REG_A].mValue; + break; + + case ASMIT_EOR: + data.mRegs[CPU_REG_A].mMask = 0; + break; + + case ASMIT_TXA: + case ASMIT_TYA: + data.mRegs[CPU_REG_A].mMask = 0; + break; + + case ASMIT_INC: + case ASMIT_DEC: + case ASMIT_STX: + case ASMIT_STY: + if (mMode == ASMIM_ZERO_PAGE) + data.mRegs[mAddress].mMask = 0; + break; + + case ASMIT_ASL: + if (iaddr >= 0) + { + int mask = data.mRegs[iaddr].mMask, value = data.mRegs[iaddr].mValue; + + data.mRegs[iaddr].mMask = ((mask << 1) & 0xff) | 0x01; + data.mRegs[iaddr].mValue = ((value << 1) & 0xff); + + if (mask & 0x80) + { + data.mRegs[CPU_REG_C].mMask = 1; + data.mRegs[CPU_REG_C].mValue = value >> 7; + } + else + data.mRegs[CPU_REG_C].mMask = 0; + + if (mMode == ASMIM_IMPLIED && data.mRegs[CPU_REG_A].mMask == 0xff && data.mRegs[CPU_REG_C].mMask) + { + carryop = data.mRegs[CPU_REG_C].mValue ? ASMIT_SEC : ASMIT_CLC; + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else + data.mRegs[CPU_REG_C].mMask = 0; + break; + + case ASMIT_LSR: + if (iaddr >= 0) + { + int mask = data.mRegs[iaddr].mMask, value = data.mRegs[iaddr].mValue; + + data.mRegs[iaddr].mMask = ((mask >> 1) & 0xff) | 0x80; + data.mRegs[iaddr].mValue = ((value >> 1) & 0x7f); + + if (mask & 0x01) + { + data.mRegs[CPU_REG_C].mMask = 1; + data.mRegs[CPU_REG_C].mValue = value & 1; + } + else + data.mRegs[CPU_REG_C].mMask = 0; + + if (mMode == ASMIM_IMPLIED && data.mRegs[CPU_REG_A].mMask == 0xff && data.mRegs[CPU_REG_C].mMask) + { + carryop = data.mRegs[CPU_REG_C].mValue ? ASMIT_SEC : ASMIT_CLC; + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else + data.mRegs[CPU_REG_C].mMask = 0; + break; + + case ASMIT_ROL: + if (iaddr >= 0) + { + int mask = data.mRegs[iaddr].mMask, value = data.mRegs[iaddr].mValue; + + data.mRegs[iaddr].mMask = (mask << 1) & 0xff; + data.mRegs[iaddr].mValue = (value << 1) & 0xff; + + if (data.mRegs[CPU_REG_C].mMask & 1) + { + data.mRegs[iaddr].mMask |= 1; + data.mRegs[iaddr].mValue |= data.mRegs[CPU_REG_C].mValue & 1; + } + + if (mask & 0x80) + { + data.mRegs[CPU_REG_C].mMask = 1; + data.mRegs[CPU_REG_C].mValue = value >> 7; + } + else + data.mRegs[CPU_REG_C].mMask = 0; + + if (mMode == ASMIM_IMPLIED && data.mRegs[CPU_REG_A].mMask == 0xff && data.mRegs[CPU_REG_C].mMask) + { + carryop = data.mRegs[CPU_REG_C].mValue ? ASMIT_SEC : ASMIT_CLC; + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else + data.mRegs[CPU_REG_C].mMask = 0; + break; + + case ASMIT_ROR: + if (iaddr >= 0) + { + int mask = data.mRegs[iaddr].mMask, value = data.mRegs[iaddr].mValue; + + data.mRegs[iaddr].mMask = (mask >> 1) & 0xff; + data.mRegs[iaddr].mValue = (value >> 1) & 0x7f; + + if (data.mRegs[CPU_REG_C].mMask & 1) + { + data.mRegs[iaddr].mMask |= 0x80; + data.mRegs[iaddr].mValue |= (data.mRegs[CPU_REG_C].mValue << 7) & 0x80; + } + + if (mask & 0x01) + { + data.mRegs[CPU_REG_C].mMask = 1; + data.mRegs[CPU_REG_C].mValue = value & 1; + } + else + data.mRegs[CPU_REG_C].mMask = 0; + + if (mMode == ASMIM_IMPLIED && data.mRegs[CPU_REG_A].mMask == 0xff && data.mRegs[CPU_REG_C].mMask) + { + carryop = data.mRegs[CPU_REG_C].mValue ? ASMIT_SEC : ASMIT_CLC; + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } + } + else + data.mRegs[CPU_REG_C].mMask = 0; + break; + } + + return changed; +} + bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsType& carryop, bool initial, bool final) { bool changed = false; @@ -10107,7 +10432,14 @@ bool NativeCodeBasicBlock::ForwardAccuAddSub(void) for (int j = apred; j < i; j++) mIns[j].mLive |= LIVE_CPU_REG_A; - mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + if (mIns[i].mLive & LIVE_CPU_REG_Z) + { + mIns[i].mType = ASMIT_ORA; mIns[i].mMode = ASMIM_IMMEDIATE; mIns[i].mAddress = 0; + } + else + { + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + } changed = true; } else if (i + 2 < mIns.Size() && mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && !(mIns[i + 2].mLive & LIVE_CPU_REG_C)) @@ -11031,6 +11363,66 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } +#if 1 + if (mIns.Size() >= 1 && mFalseJump) + { + int sz = mIns.Size(); + + if (mIns[sz - 1].mType == ASMIT_CMP || mIns[sz - 1].mType == ASMIT_CPX || mIns[sz - 1].mType == ASMIT_CPY) + { + if (mBranch == ASMIT_BEQ) + { + if (mFalseJump->mNumEntries == 1 && mTrueJump->mNumEntries == 2 && mFalseJump->mIns.Size() == 0) + { + if (mFalseJump->mBranch == ASMIT_BCC) + { + if (mFalseJump->mFalseJump == mTrueJump) + { + mBranch = ASMIT_BCS; + mFalseJump = mFalseJump->mFalseJump; + changed = true; + } + } + else if (mFalseJump->mBranch == ASMIT_BCS) + { + if (mFalseJump->mTrueJump == mTrueJump) + { + mBranch = ASMIT_BCS; + mFalseJump = mFalseJump->mTrueJump; + changed = true; + } + } + } + } + else if (mBranch == ASMIT_BNE) + { + if (mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 2 && mTrueJump->mIns.Size() == 0) + { + if (mTrueJump->mBranch == ASMIT_BCC) + { + if (mTrueJump->mFalseJump == mFalseJump) + { + mBranch = ASMIT_BCC; + mTrueJump = mTrueJump->mTrueJump; + changed = true; + } + } + else if (mTrueJump->mBranch == ASMIT_BCS) + { + if (mTrueJump->mTrueJump == mFalseJump) + { + mBranch = ASMIT_BCC; + mTrueJump = mTrueJump->mFalseJump; + changed = true; + } + } + } + } + } + + } +#endif + if (mTrueJump && mTrueJump->ExpandADCToBranch(proc)) changed = true; if (mFalseJump && mFalseJump->ExpandADCToBranch(proc)) @@ -12783,10 +13175,12 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to) return false; } + int live = mIns[to].mLive; mIns.Remove(to); for (int i = start; i < from; i++) { mIns.Insert(to, mIns[start]); + mIns[to].mLive |= live; mIns.Remove(start); } mIns.Remove(start); @@ -12804,10 +13198,12 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to) return false; } + int live = mIns[to].mLive; mIns.Remove(to); for (int i = start; i < from; i++) { mIns.Insert(to, mIns[start]); + mIns[to].mLive |= live; mIns.Remove(start); } mIns.Remove(start); @@ -12829,10 +13225,12 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to) return false; } + int live = mIns[to].mLive; mIns.Remove(to); for (int i = start; i < from; i++) { mIns.Insert(to, mIns[start]); + mIns[to].mLive |= live; mIns.Remove(start); } mIns.Remove(start); @@ -12857,16 +13255,22 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to) start--; + int plive = mIns[start].mLive; + for (int i = from; i < to; i++) + mIns[i].mLive |= plive; + if (mIns[to].mLive & LIVE_CPU_REG_Y) { for (int i = start; i < from; i++) mIns[i].mLive |= LIVE_CPU_REG_Y; } + int live = mIns[to].mLive; mIns.Remove(to); for (int i = start; i < from; i++) { mIns.Insert(to, mIns[start]); + mIns[to].mLive |= live; mIns.Remove(start); } mIns.Remove(start); @@ -13552,6 +13956,63 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreDown(int at) return false; } +bool NativeCodeBasicBlock::MoveLoadIndirectTempStoreUp(int at) +{ + // ldy #imm + // lda (t0), y + // sta t1 + + int j = at - 1; + while (j >= 3) + { + if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && (mIns[j].mAddress == mIns[at + 1].mAddress || mIns[j].mAddress == mIns[at + 1].mAddress + 1)) + { + if (mIns[j - 3].mType == ASMIT_LDA && mIns[j - 3].mMode == ASMIM_ZERO_PAGE && + mIns[j - 2].mType == ASMIT_STA && mIns[j - 2].mMode == ASMIM_ZERO_PAGE && + mIns[j - 1].mType == ASMIT_LDA && mIns[j - 1].mMode == ASMIM_ZERO_PAGE && + mIns[j - 0].mType == ASMIT_STA && mIns[j - 0].mMode == ASMIM_ZERO_PAGE) + { + if (mIns[j - 2].mAddress == mIns[at + 1].mAddress && + mIns[j - 0].mAddress == mIns[at + 1].mAddress + 1 && + mIns[j - 1].mAddress == mIns[j - 3].mAddress + 1) + { + mIns[at + 1].mLive |= mIns[j].mLive; + mIns[at + 2].mLive |= mIns[j].mLive; + mIns[at + 3].mLive |= mIns[j].mLive; + + mIns[at + 1].mAddress = mIns[j - 3].mAddress; + mIns[at + 1].mLive |= LIVE_MEM; + + mIns.Insert(j + 1, mIns[at + 2]); + mIns.Insert(j + 1, mIns[at + 2]); + mIns.Insert(j + 1, mIns[at + 2]); + + mIns.Remove(at + 3); + mIns.Remove(at + 3); + mIns.Remove(at + 3); + + return true; + } + } + + return false; + } + + if (mIns[j].ReferencesYReg()) + return false; + if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress)) + return false; + if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress + 1)) + return false; + if (mIns[j].ReferencesZeroPage(mIns[at + 2].mAddress)) + return false; + + j--; + } + + return false; +} + bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at) { int j = at - 1; @@ -14394,6 +14855,60 @@ bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreDown(int at) return false; } +bool NativeCodeBasicBlock::BitFieldForwarding(const NativeRegisterDataSet& data) +{ + bool changed = false; + + if (!mVisited) + { + mNDataSet = data; + + if (mLoopHead) + { + mNDataSet.ResetMask(); + } + else if (mNumEntries > 0) + { + if (mNumEntered > 0) + mNDataSet.IntersectMask(mDataSet); + + mNumEntered++; + + if (mNumEntered < mNumEntries) + { + mDataSet = mNDataSet; + return false; + } + } + + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + AsmInsType carryop = ASMIT_NOP; + + if (mIns[i].BitFieldForwarding(mNDataSet, carryop)) + changed = true; + if (carryop != ASMIT_NOP) + mIns.Insert(i + 1, NativeCodeInstruction(carryop)); + } + + + if (mFalseJump) + { + mFDataSet = mNDataSet; + + } + + if (this->mTrueJump && this->mTrueJump->BitFieldForwarding(mNDataSet)) + changed = true; + if (this->mFalseJump && this->mFalseJump->BitFieldForwarding(mFDataSet)) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final) { bool changed = false; @@ -14509,10 +15024,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE) { mBranch = ASMIT_JMP; + mTrueJump->mNumEntries--; if (!mNDataSet.mRegs[CPU_REG_C].mValue) mTrueJump = fork->mFalseJump; else mTrueJump = fork->mTrueJump; + mTrueJump->mNumEntries++; + if (mFalseJump) + mFalseJump->mNumEntries--; mFalseJump = nullptr; changed = true; } @@ -14521,10 +15040,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE) { mBranch = ASMIT_JMP; + mTrueJump->mNumEntries--; if (mNDataSet.mRegs[CPU_REG_C].mValue) mTrueJump = fork->mFalseJump; else mTrueJump = fork->mTrueJump; + mTrueJump->mNumEntries++; + if (mFalseJump) + mFalseJump->mNumEntries--; mFalseJump = nullptr; changed = true; } @@ -14533,10 +15056,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) { mBranch = ASMIT_JMP; + mTrueJump->mNumEntries--; if (!mNDataSet.mRegs[CPU_REG_Z].mValue) mTrueJump = fork->mFalseJump; else mTrueJump = fork->mTrueJump; + mTrueJump->mNumEntries++; + if (mFalseJump) + mFalseJump->mNumEntries--; mFalseJump = nullptr; changed = true; } @@ -14562,10 +15089,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) { mBranch = ASMIT_JMP; + mTrueJump->mNumEntries--; if (mNDataSet.mRegs[CPU_REG_Z].mValue) mTrueJump = fork->mFalseJump; else mTrueJump = fork->mTrueJump; + mTrueJump->mNumEntries++; + if (mFalseJump) + mFalseJump->mNumEntries--; mFalseJump = nullptr; changed = true; } @@ -14574,10 +15105,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) { mBranch = ASMIT_JMP; + mTrueJump->mNumEntries--; if ((mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80)) mTrueJump = fork->mFalseJump; else mTrueJump = fork->mTrueJump; + mTrueJump->mNumEntries++; + if (mFalseJump) + mFalseJump->mNumEntries--; mFalseJump = nullptr; changed = true; } @@ -14586,10 +15121,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) { mBranch = ASMIT_JMP; + mTrueJump->mNumEntries--; if (!(mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80)) mTrueJump = fork->mFalseJump; else mTrueJump = fork->mTrueJump; + mTrueJump->mNumEntries++; + if (mFalseJump) + mFalseJump->mNumEntries--; mFalseJump = nullptr; changed = true; } @@ -17490,6 +18029,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif +#if 1 + // move load (),y store zp up to potential user + for (int i = 4; i + 2 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 1].mLive & LIVE_MEM) && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_Y))) + { + if (MoveLoadIndirectTempStoreUp(i)) + changed = true; + } + } + CheckLive(); + +#endif + #if 1 // move load - store abs up to initial store // @@ -18065,6 +18620,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass // Replace (a & 0x80) != 0 with bpl/bmi int sz = mIns.Size(); + #if 1 if (sz > 1 && mIns[sz - 2].ChangesAccuAndFlag() && @@ -19994,7 +20550,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_LDA; mIns[i + 3].mLive |= LIVE_CPU_REG_C; - mIns[i + 4].mType = ASMIT_SBC; + mIns[i + 4].mType = ASMIT_SBC; mIns[i + 4].mLive |= LIVE_CPU_REG_C; + + if (mIns[i + 4].RequiresYReg()) + { + mIns[i + 2].mLive |= LIVE_CPU_REG_Y; + mIns[i + 3].mLive |= LIVE_CPU_REG_Y; + } + if (mIns[i + 4].RequiresXReg()) + { + mIns[i + 2].mLive |= LIVE_CPU_REG_X; + mIns[i + 3].mLive |= LIVE_CPU_REG_X; + } progress = true; } @@ -20731,7 +21298,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 4].mType == ASMIT_INY && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_TYA; mIns[i + 0].mLive |= LIVE_CPU_REG_A; - mIns[i + 1].mType = ASMIT_CLC; mIns[i + 1].mLive |= LIVE_CPU_REG_A; + mIns[i + 1].mType = ASMIT_CLC; mIns[i + 1].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_C; mIns[i + 2].mType = ASMIT_ADC; mIns[i + 2].mMode = ASMIM_IMMEDIATE; mIns[i + 2].mAddress = 5; mIns[i + 2].mLive |= LIVE_CPU_REG_A; mIns[i + 3].mType = ASMIT_TAY; mIns[i + 4].mType = ASMIT_NOP; @@ -20745,7 +21312,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 4].mType == ASMIT_INX && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_TXA; mIns[i + 0].mLive |= LIVE_CPU_REG_A; - mIns[i + 1].mType = ASMIT_CLC; mIns[i + 1].mLive |= LIVE_CPU_REG_A; + mIns[i + 1].mType = ASMIT_CLC; mIns[i + 1].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_C; mIns[i + 2].mType = ASMIT_ADC; mIns[i + 2].mMode = ASMIM_IMMEDIATE; mIns[i + 2].mAddress = 5; mIns[i + 2].mLive |= LIVE_CPU_REG_A; mIns[i + 3].mType = ASMIT_TAX; mIns[i + 4].mType = ASMIT_NOP; @@ -21069,6 +21636,47 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif +#if 0 + if (i + 13 < mIns.Size()) + { + if (mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1) + { + printf("CHECK\n"); + } + + if (mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_LDA && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + mIns[i + 4].mType == ASMIT_LDA && + mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mAddress == 0 && + mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && + + mIns[i + 7].mType == ASMIT_CLC && + mIns[i + 8].mType == ASMIT_LDA && mIns[i + 8].mMode == ASMIM_ZERO_PAGE && mIns[i + 8].mAddress == mIns[i + 3].mAddress && !(mIns[i + 8].mLive & LIVE_MEM) && + mIns[i + 9].mType == ASMIT_ADC && + mIns[i + 10].mType == ASMIT_STA && + mIns[i + 11].mType == ASMIT_LDA && mIns[i + 11].mMode == ASMIM_ZERO_PAGE && mIns[i + 11].mAddress == mIns[i + 6].mAddress && !(mIns[i + 11].mLive & LIVE_MEM) && + mIns[i + 12].mType == ASMIT_ADC && + mIns[i + 12].mType == ASMIT_STA) + { + mIns[i + 7].CopyMode(mIns[i + 0]); + mIns[i + 11].CopyMode(mIns[i + 4]); + mIns[i + 8].mType = ASMIT_SEC; + + for (int j = 0; j < 7; j++) + { + mIns[i + j].mType = ASMIT_NOP; + mIns[i + j].mMode = ASMIM_IMPLIED; + mIns[i + j + 7].mLive |= mIns[i + 0].mLive; + } + + progress = true; + } + + } +#endif + #endif #if 1 if (pass > 1 && mIns[i].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[i].mLinkerObject && (mIns[i].mFlags & NCIF_LOWER) && !(mIns[i].mAddress & 0xff) && !(mIns[i].mLinkerObject->mAlignment & 0xff)) @@ -22102,6 +22710,20 @@ void NativeCodeProcedure::Optimize(void) mEntryBlock->BuildDominatorTree(nullptr); +#if 1 + if (step > 3) + { + NativeRegisterDataSet data; + + bool bchanged; + do { + ResetVisited(); + bchanged = mEntryBlock->BitFieldForwarding(data); + } while (bchanged); + + } +#endif + #if 1 do { @@ -22116,6 +22738,7 @@ void NativeCodeProcedure::Optimize(void) } while (changed); #endif + #if 1 ResetVisited(); if (mEntryBlock->PeepHoleOptimizer(this, step)) @@ -22298,10 +22921,14 @@ void NativeCodeProcedure::Optimize(void) if (mEntryBlock->ForwardAccuAddSub()) changed = true; +#endif +#if 1 ResetVisited(); if (mEntryBlock->ForwardZpYIndex(step >= 4)) changed = true; +#endif +#if 1 ResetVisited(); if (mEntryBlock->ForwardZpXIndex(step >= 4)) changed = true; @@ -22596,6 +23223,13 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], nullptr, ins, false); i++; } + else if (i + 2 < iblock->mInstructions.Size() && ins->mOperator == IA_NEG && + iblock->mInstructions[i + 2]->mCode == IC_LEA && iblock->mInstructions[i + 2]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[0].mFinal && + iblock->mInstructions[i + 1]->mCode == IC_LOAD && iblock->mInstructions[i + 2]->mSrc[1].mTemp == iblock->mInstructions[i + 1]->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[1].mFinal) + { + block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 2], iblock->mInstructions[i + 1], ins, false); + i+=2; + } else block->UnaryOperator(iproc, this, ins); break; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 255b9c0..cbee523 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -20,13 +20,14 @@ enum NativeRegisterDataMode struct NativeRegisterData { NativeRegisterDataMode mMode; - int mValue; + int mValue, mMask; uint32 mFlags; LinkerObject * mLinkerObject; NativeRegisterData(void); void Reset(void); + void ResetMask(void); bool SameData(const NativeRegisterData& d) const; }; @@ -36,10 +37,13 @@ struct NativeRegisterDataSet NativeRegisterData mRegs[261]; void Reset(void); + void ResetMask(void); + void ResetZeroPage(int addr); void ResetAbsolute(LinkerObject * linkerObject, int addr); void ResetIndirect(void); void Intersect(const NativeRegisterDataSet& set); + void IntersectMask(const NativeRegisterDataSet& set); }; @@ -76,6 +80,7 @@ public: void Assemble(NativeCodeBasicBlock* block); void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps); bool IsUsedResultInstructions(NumberSet& requiredTemps); + bool BitFieldForwarding(NativeRegisterDataSet& data, AsmInsType& carryop); bool ValueForwarding(NativeRegisterDataSet& data, AsmInsType & carryop, bool initial, bool final); void Simulate(NativeRegisterDataSet& data); @@ -241,6 +246,7 @@ public: bool MoveIndirectLoadStoreUp(int at); bool MoveAbsoluteLoadStoreUp(int at); bool MoveLoadStoreOutOfXYRangeUp(int at); + bool MoveLoadIndirectTempStoreUp(int at); bool MoveLoadAddImmStoreAbsXUp(int at); bool MoveStaTaxLdaStaDown(int at); @@ -289,6 +295,7 @@ public: bool ReverseReplaceTAX(int at); bool ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final); + bool BitFieldForwarding(const NativeRegisterDataSet& data); void CollectEntryBlocks(NativeCodeBasicBlock* block); diff --git a/oscar64/Preprocessor.cpp b/oscar64/Preprocessor.cpp index 65c905a..88743c1 100644 --- a/oscar64/Preprocessor.cpp +++ b/oscar64/Preprocessor.cpp @@ -20,6 +20,96 @@ SourcePath::~SourcePath(void) } +bool SourceFile::ReadLineLZO(char* line) +{ + if (mPos > 256) + { + memmove(mBuffer, mBuffer + mPos - 256, mFill + 256 - mPos); + mFill -= mPos - 256; + mPos = 256; + } + + assert(mFill >= 0 && mFill - mPos < 384 && mPos <= mFill); + + int c; + while (mLimit && mFill < 384 && (c = fgetc(mFile)) >= 0) + { + mLimit--; + mBuffer[mFill++] = c; + } + + if (mPos < mFill) + { + int pi = 0; + while (pi < 127 && mPos < mFill) + { + int bi = pi, bj = 0; + for (int i = 1; i < mPos; i++) + { + int j = 0; + while (j < 127 && mPos + j < mFill && mBuffer[mPos - i + j] == mBuffer[mPos + j]) + j++; + + if (j > bj) + { + bi = i; + bj = j; + } + } + + if (bj >= 4) + { + if (pi > 0) + { + sprintf_s(line, 1024, "0x%02x, ", pi); + + for (int i = 0; i < pi; i++) + { + char buffer[16]; + sprintf_s(buffer, 16, "0x%02x, ", (unsigned char)mBuffer[mPos - pi + i]); + + strcat_s(line, 1024, buffer); + } + + return true; + } + else + { + sprintf_s(line, 1024, "0x%02x, 0x%02x, ", 128 + bj, bi); + mPos += bj; + + if (mFill == mPos) + strcat_s(line, 1024, "0x00, "); + + return true; + } + } + else + { + mPos++; + pi++; + } + } + + sprintf_s(line, 1024, "0x%02x, ", pi); + + for (int i = 0; i < pi; i++) + { + char buffer[16]; + sprintf_s(buffer, 16, "0x%02x, ", (unsigned char)mBuffer[mPos - pi + i]); + + strcat_s(line, 1024, buffer); + } + + if (mFill == mPos) + strcat_s(line, 1024, "0x00, "); + + return true; + } + + return false; +} + bool SourceFile::ReadLineRLE(char* line) { assert(mFill >= 0 && mFill < 256); @@ -171,6 +261,10 @@ bool SourceFile::ReadLine(char* line) if (ReadLineRLE(line)) return true; break; + case SFM_BINARY_LZO: + if (ReadLineLZO(line)) + return true; + break; } fclose(mFile); @@ -233,6 +327,7 @@ bool SourceFile::Open(const char* name, const char* path, SourceFileMode mode) mMode = mode; mLimit = 0x10000; mFill = 0; + mPos = 0; return true; } diff --git a/oscar64/Preprocessor.h b/oscar64/Preprocessor.h index 39fcb50..28fade1 100644 --- a/oscar64/Preprocessor.h +++ b/oscar64/Preprocessor.h @@ -18,7 +18,8 @@ enum SourceFileMode { SFM_TEXT, SFM_BINARY, - SFM_BINARY_RLE + SFM_BINARY_RLE, + SFM_BINARY_LZO }; class SourceFile { @@ -31,12 +32,13 @@ public: SourceFileMode mMode; int mLimit; - char mBuffer[256]; - int mFill; + char mBuffer[512]; + int mFill, mPos; bool ReadLine(char* line); bool ReadLineRLE(char* line); + bool ReadLineLZO(char* line); SourceFile(void); ~SourceFile(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 43b3571..b5cd62d 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -656,6 +656,8 @@ void Scanner::NextToken(void) { if (!strcmp(mTokenIdent->mString, "rle")) mode = SFM_BINARY_RLE; + else if (!strcmp(mTokenIdent->mString, "lzo")) + mode = SFM_BINARY_LZO; else mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Invalid embed compression mode", mTokenIdent); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 595bb41..7dde4f8 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -73,7 +73,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.5.121"); + strcpy(strProductVersion, "1.6.123"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index f35c2a6..e7d4cd9 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,121,0 - PRODUCTVERSION 1,5,121,0 + FILEVERSION 1,6,123,0 + PRODUCTVERSION 1,6,123,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.5.121.0" + VALUE "FileVersion", "1.6.123.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.5.121.0" + VALUE "ProductVersion", "1.6.123.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 712b460..b0d8ca7 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -130,6 +130,12 @@ } "Entry" { + "MsmKey" = "8:_24F2466589154E2DAA108C2EDB3BB432" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_29ED5D9B606D45DA80CFF329A7643DC8" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -274,6 +280,12 @@ } "Entry" { + "MsmKey" = "8:_557F7BC3AD794C4A93D5DFDA00024E1B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_5832EB4DC2134FF0BB7872666547CA0B" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -664,6 +676,12 @@ } "Entry" { + "MsmKey" = "8:_CA8FE59769D748A5BF04ABC3F9154DBA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_CC473A7B399D4B31A9DC8C94F7771EF7" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1327,6 +1345,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_24F2466589154E2DAA108C2EDB3BB432" + { + "SourcePath" = "8:..\\include\\oscar.c" + "TargetName" = "8:oscar.c" + "Tag" = "8:" + "Folder" = "8:_7C0D28C244F14A21B5F72213BBE59B6F" + "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}:_29ED5D9B606D45DA80CFF329A7643DC8" { "SourcePath" = "8:..\\samples\\kernalio\\diskdir.c" @@ -1807,6 +1845,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_557F7BC3AD794C4A93D5DFDA00024E1B" + { + "SourcePath" = "8:..\\samples\\memmap\\charsetexpand.c" + "TargetName" = "8:charsetexpand.c" + "Tag" = "8:" + "Folder" = "8:_A62A71A6A08941C5964B90112D87731F" + "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}:_5832EB4DC2134FF0BB7872666547CA0B" { "SourcePath" = "8:..\\samples\\sprites\\make.bat" @@ -3107,6 +3165,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CA8FE59769D748A5BF04ABC3F9154DBA" + { + "SourcePath" = "8:..\\include\\oscar.h" + "TargetName" = "8:oscar.h" + "Tag" = "8:" + "Folder" = "8:_7C0D28C244F14A21B5F72213BBE59B6F" + "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}:_CC473A7B399D4B31A9DC8C94F7771EF7" { "SourcePath" = "8:..\\samples\\memmap\\charsethi.c" @@ -4023,15 +4101,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{9712E64F-8FDC-4FD2-BE20-8889E458BC89}" - "PackageCode" = "8:{63C93E1F-200E-43F4-8A18-C9A7743F2543}" + "ProductCode" = "8:{F66E2274-2B16-49B2-950F-83A3DC2EEA9D}" + "PackageCode" = "8:{4F43842C-6F90-403A-8CE1-352F775F975F}" "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.5.121" + "ProductVersion" = "8:1.6.123" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" @@ -4545,7 +4623,7 @@ { "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6" { - "SourcePath" = "8:..\\Debug\\oscar64.exe" + "SourcePath" = "8:..\\Release\\oscar64.exe" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4" diff --git a/samples/memmap/build.sh b/samples/memmap/build.sh index c55e053..214ec30 100644 --- a/samples/memmap/build.sh +++ b/samples/memmap/build.sh @@ -4,6 +4,7 @@ ../../bin/oscar64 charsetlo.c ../../bin/oscar64 charsethi.c ../../bin/oscar64 charsetcopy.c +../../bin/oscar64 charsetexpand.c ../../bin/oscar64 easyflash.c -n -tf=crt ../../bin/oscar64 easyflashreloc.c -n -tf=crt ../../bin/oscar64 easyflashshared.c -n -tf=crt diff --git a/samples/memmap/charsetexpand.c b/samples/memmap/charsetexpand.c new file mode 100644 index 0000000..ee1a7a0 --- /dev/null +++ b/samples/memmap/charsetexpand.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +// make space until 0xcc00 by extending the default region + +#pragma region( main, 0x0a00, 0xcc00, , , {code, data, bss, heap, stack} ) + +// space for our custom charset from c000 to c800, will be copied to +// 0xd000 during startup to free space for stack and heap + +#pragma section( charset, 0) + +#pragma region( charset, 0xc000, 0xc800, , , {charset} ) + +// set initialized data segment to charset section + +#pragma data(charset) + +// lz compressed data +char charset[] = { + #embed 2048 0 lzo "../resources/charset.bin" +} + +// back to normal + +#pragma data(data) + +// pointers to charset and screen in memory + +#define Screen ((char *)0xcc00) +#define Charset ((char *)0xd000) + +int main(void) +{ + // Install the trampoline + mmap_trampoline(); + + // make all of RAM visibile to the CPU + mmap_set(MMAP_RAM); + + // expand the font + oscar_expand_lzo(Charset, charset); + + // make lower part of RAM visible to CPU + mmap_set(MMAP_NO_BASIC); + + // map the vic to the new charset + + vic_setmode(VICM_TEXT, Screen, Charset) + + for(int i=0; i<1000; i++) + Screen[i] = (char)i; + + // wait for keypress + + getchar(); + + // restore VIC + + vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000) + + // restore basic ROM + mmap_set(MMAP_ROM); + + return 0; +} + diff --git a/samples/memmap/make.bat b/samples/memmap/make.bat index c3ab0ed..8e4e863 100644 --- a/samples/memmap/make.bat +++ b/samples/memmap/make.bat @@ -3,6 +3,7 @@ call ..\..\bin\oscar64 allmem.c call ..\..\bin\oscar64 charsetlo.c call ..\..\bin\oscar64 charsethi.c call ..\..\bin\oscar64 charsetcopy.c +call ..\..\bin\oscar64 charsetexpand.c call ..\..\bin\oscar64 easyflash.c -n -tf=crt call ..\..\bin\oscar64 easyflashreloc.c -n -tf=crt call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt