Add lz compression for embedded assets

This commit is contained in:
drmortalwombat 2022-05-01 12:55:13 +02:00
parent 62d08e139b
commit ea1fa189b2
17 changed files with 1023 additions and 24 deletions

View File

@ -29,6 +29,8 @@ void sidfx_init(void)
}
void sidfx_play(byte chn, SIDFX * fx, byte cnt)
{
if (!channels[chn].com || channels[chn].com->priority <= fx->priority)
{
if (channels[chn].state == SIDFX_IDLE)
channels[chn].state = SIDFX_READY;
@ -38,6 +40,7 @@ void sidfx_play(byte chn, SIDFX * fx, byte cnt)
channels[chn].com = fx;
channels[chn].cnt = cnt - 1;
}
}
void sidfx_stop(byte chn)
{

View File

@ -9,6 +9,7 @@ struct SIDFX
byte ctrl, attdec, susrel;
int dfreq, dpwm;
byte time1, time0;
byte priority;
};
void sidfx_init(void);

View File

@ -6,6 +6,7 @@
#include <stdlib.h>
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

View File

@ -5,6 +5,7 @@
#define NUM_IRQS 16
extern volatile byte rirq_count;
enum RIRQCodeIndex
{

88
include/oscar.c Normal file
View File

@ -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;
}

12
include/oscar.h Normal file
View File

@ -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

View File

@ -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;
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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -0,0 +1,71 @@
#include <c64/vic.h>
#include <c64/memmap.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <oscar.h>
// 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;
}

View File

@ -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