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

View File

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

View File

@ -6,6 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
volatile char npos = 1, tpos = 0; volatile char npos = 1, tpos = 0;
volatile byte rirq_count;
byte rasterIRQRows[NUM_IRQS]; byte rasterIRQRows[NUM_IRQS];
byte rasterIRQIndex[NUM_IRQS]; byte rasterIRQIndex[NUM_IRQS];
@ -62,6 +63,7 @@ w1:
e2: e2:
ldx npos ldx npos
stx tpos stx tpos
inc rirq_count
bit $d011 bit $d011
bmi e1 bmi e1
@ -135,6 +137,7 @@ w1:
e2: e2:
ldx npos ldx npos
stx tpos stx tpos
inc rirq_count
bit $d011 bit $d011
bmi e1 bmi e1

View File

@ -5,6 +5,7 @@
#define NUM_IRQS 16 #define NUM_IRQS 16
extern volatile byte rirq_count;
enum RIRQCodeIndex 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; static int GlobalValueNumber = 0;
NativeRegisterData::NativeRegisterData(void) 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++; mValue = GlobalValueNumber++;
} }
void NativeRegisterData::ResetMask(void)
{
mMask = 0;
}
bool NativeRegisterData::SameData(const NativeRegisterData& d) const bool NativeRegisterData::SameData(const NativeRegisterData& d) const
{ {
if (mMode != d.mMode) if (mMode != d.mMode)
@ -56,6 +61,14 @@ void NativeRegisterDataSet::Reset(void)
mRegs[i].Reset(); mRegs[i].Reset();
} }
void NativeRegisterDataSet::ResetMask(void)
{
for (int i = 0; i < NUM_REGS; i++)
mRegs[i].ResetMask();
}
void NativeRegisterDataSet::ResetZeroPage(int addr) void NativeRegisterDataSet::ResetZeroPage(int addr)
{ {
mRegs[addr].Reset(); 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) 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 NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsType& carryop, bool initial, bool final)
{ {
bool changed = false; bool changed = false;
@ -10107,7 +10432,14 @@ bool NativeCodeBasicBlock::ForwardAccuAddSub(void)
for (int j = apred; j < i; j++) for (int j = apred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_A; 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; mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED;
}
changed = true; 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)) 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)) if (mTrueJump && mTrueJump->ExpandADCToBranch(proc))
changed = true; changed = true;
if (mFalseJump && mFalseJump->ExpandADCToBranch(proc)) if (mFalseJump && mFalseJump->ExpandADCToBranch(proc))
@ -12783,10 +13175,12 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
return false; return false;
} }
int live = mIns[to].mLive;
mIns.Remove(to); mIns.Remove(to);
for (int i = start; i < from; i++) for (int i = start; i < from; i++)
{ {
mIns.Insert(to, mIns[start]); mIns.Insert(to, mIns[start]);
mIns[to].mLive |= live;
mIns.Remove(start); mIns.Remove(start);
} }
mIns.Remove(start); mIns.Remove(start);
@ -12804,10 +13198,12 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
return false; return false;
} }
int live = mIns[to].mLive;
mIns.Remove(to); mIns.Remove(to);
for (int i = start; i < from; i++) for (int i = start; i < from; i++)
{ {
mIns.Insert(to, mIns[start]); mIns.Insert(to, mIns[start]);
mIns[to].mLive |= live;
mIns.Remove(start); mIns.Remove(start);
} }
mIns.Remove(start); mIns.Remove(start);
@ -12829,10 +13225,12 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
return false; return false;
} }
int live = mIns[to].mLive;
mIns.Remove(to); mIns.Remove(to);
for (int i = start; i < from; i++) for (int i = start; i < from; i++)
{ {
mIns.Insert(to, mIns[start]); mIns.Insert(to, mIns[start]);
mIns[to].mLive |= live;
mIns.Remove(start); mIns.Remove(start);
} }
mIns.Remove(start); mIns.Remove(start);
@ -12857,16 +13255,22 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
start--; 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) if (mIns[to].mLive & LIVE_CPU_REG_Y)
{ {
for (int i = start; i < from; i++) for (int i = start; i < from; i++)
mIns[i].mLive |= LIVE_CPU_REG_Y; mIns[i].mLive |= LIVE_CPU_REG_Y;
} }
int live = mIns[to].mLive;
mIns.Remove(to); mIns.Remove(to);
for (int i = start; i < from; i++) for (int i = start; i < from; i++)
{ {
mIns.Insert(to, mIns[start]); mIns.Insert(to, mIns[start]);
mIns[to].mLive |= live;
mIns.Remove(start); mIns.Remove(start);
} }
mIns.Remove(start); mIns.Remove(start);
@ -13552,6 +13956,63 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreDown(int at)
return false; 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) bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
{ {
int j = at - 1; int j = at - 1;
@ -14394,6 +14855,60 @@ bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreDown(int at)
return false; 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 NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final)
{ {
bool changed = false; bool changed = false;
@ -14509,10 +15024,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE) if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
{ {
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mTrueJump->mNumEntries--;
if (!mNDataSet.mRegs[CPU_REG_C].mValue) if (!mNDataSet.mRegs[CPU_REG_C].mValue)
mTrueJump = fork->mFalseJump; mTrueJump = fork->mFalseJump;
else else
mTrueJump = fork->mTrueJump; mTrueJump = fork->mTrueJump;
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries--;
mFalseJump = nullptr; mFalseJump = nullptr;
changed = true; changed = true;
} }
@ -14521,10 +15040,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE) if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
{ {
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mTrueJump->mNumEntries--;
if (mNDataSet.mRegs[CPU_REG_C].mValue) if (mNDataSet.mRegs[CPU_REG_C].mValue)
mTrueJump = fork->mFalseJump; mTrueJump = fork->mFalseJump;
else else
mTrueJump = fork->mTrueJump; mTrueJump = fork->mTrueJump;
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries--;
mFalseJump = nullptr; mFalseJump = nullptr;
changed = true; changed = true;
} }
@ -14533,10 +15056,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
{ {
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mTrueJump->mNumEntries--;
if (!mNDataSet.mRegs[CPU_REG_Z].mValue) if (!mNDataSet.mRegs[CPU_REG_Z].mValue)
mTrueJump = fork->mFalseJump; mTrueJump = fork->mFalseJump;
else else
mTrueJump = fork->mTrueJump; mTrueJump = fork->mTrueJump;
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries--;
mFalseJump = nullptr; mFalseJump = nullptr;
changed = true; changed = true;
} }
@ -14562,10 +15089,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
{ {
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mTrueJump->mNumEntries--;
if (mNDataSet.mRegs[CPU_REG_Z].mValue) if (mNDataSet.mRegs[CPU_REG_Z].mValue)
mTrueJump = fork->mFalseJump; mTrueJump = fork->mFalseJump;
else else
mTrueJump = fork->mTrueJump; mTrueJump = fork->mTrueJump;
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries--;
mFalseJump = nullptr; mFalseJump = nullptr;
changed = true; changed = true;
} }
@ -14574,10 +15105,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
{ {
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mTrueJump->mNumEntries--;
if ((mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80)) if ((mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = fork->mFalseJump; mTrueJump = fork->mFalseJump;
else else
mTrueJump = fork->mTrueJump; mTrueJump = fork->mTrueJump;
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries--;
mFalseJump = nullptr; mFalseJump = nullptr;
changed = true; changed = true;
} }
@ -14586,10 +15121,14 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
{ {
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mTrueJump->mNumEntries--;
if (!(mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80)) if (!(mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = fork->mFalseJump; mTrueJump = fork->mFalseJump;
else else
mTrueJump = fork->mTrueJump; mTrueJump = fork->mTrueJump;
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries--;
mFalseJump = nullptr; mFalseJump = nullptr;
changed = true; changed = true;
} }
@ -17490,6 +18029,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#endif #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 #if 1
// move load - store abs up to initial store // 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 // Replace (a & 0x80) != 0 with bpl/bmi
int sz = mIns.Size(); int sz = mIns.Size();
#if 1 #if 1
if (sz > 1 && if (sz > 1 &&
mIns[sz - 2].ChangesAccuAndFlag() && 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 + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].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 + 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; 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 + 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 + 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 + 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 + 3].mType = ASMIT_TAY;
mIns[i + 4].mType = ASMIT_NOP; 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 + 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 + 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 + 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 + 3].mType = ASMIT_TAX;
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mType = ASMIT_NOP;
@ -21069,6 +21636,47 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#endif #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 #endif
#if 1 #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)) 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); mEntryBlock->BuildDominatorTree(nullptr);
#if 1
if (step > 3)
{
NativeRegisterDataSet data;
bool bchanged;
do {
ResetVisited();
bchanged = mEntryBlock->BitFieldForwarding(data);
} while (bchanged);
}
#endif
#if 1 #if 1
do do
{ {
@ -22116,6 +22738,7 @@ void NativeCodeProcedure::Optimize(void)
} while (changed); } while (changed);
#endif #endif
#if 1 #if 1
ResetVisited(); ResetVisited();
if (mEntryBlock->PeepHoleOptimizer(this, step)) if (mEntryBlock->PeepHoleOptimizer(this, step))
@ -22298,10 +22921,14 @@ void NativeCodeProcedure::Optimize(void)
if (mEntryBlock->ForwardAccuAddSub()) if (mEntryBlock->ForwardAccuAddSub())
changed = true; changed = true;
#endif
#if 1
ResetVisited(); ResetVisited();
if (mEntryBlock->ForwardZpYIndex(step >= 4)) if (mEntryBlock->ForwardZpYIndex(step >= 4))
changed = true; changed = true;
#endif
#if 1
ResetVisited(); ResetVisited();
if (mEntryBlock->ForwardZpXIndex(step >= 4)) if (mEntryBlock->ForwardZpXIndex(step >= 4))
changed = true; changed = true;
@ -22596,6 +23223,13 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], nullptr, ins, false); block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], nullptr, ins, false);
i++; 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 else
block->UnaryOperator(iproc, this, ins); block->UnaryOperator(iproc, this, ins);
break; break;

View File

@ -20,13 +20,14 @@ enum NativeRegisterDataMode
struct NativeRegisterData struct NativeRegisterData
{ {
NativeRegisterDataMode mMode; NativeRegisterDataMode mMode;
int mValue; int mValue, mMask;
uint32 mFlags; uint32 mFlags;
LinkerObject * mLinkerObject; LinkerObject * mLinkerObject;
NativeRegisterData(void); NativeRegisterData(void);
void Reset(void); void Reset(void);
void ResetMask(void);
bool SameData(const NativeRegisterData& d) const; bool SameData(const NativeRegisterData& d) const;
}; };
@ -36,10 +37,13 @@ struct NativeRegisterDataSet
NativeRegisterData mRegs[261]; NativeRegisterData mRegs[261];
void Reset(void); void Reset(void);
void ResetMask(void);
void ResetZeroPage(int addr); void ResetZeroPage(int addr);
void ResetAbsolute(LinkerObject * linkerObject, int addr); void ResetAbsolute(LinkerObject * linkerObject, int addr);
void ResetIndirect(void); void ResetIndirect(void);
void Intersect(const NativeRegisterDataSet& set); void Intersect(const NativeRegisterDataSet& set);
void IntersectMask(const NativeRegisterDataSet& set);
}; };
@ -76,6 +80,7 @@ public:
void Assemble(NativeCodeBasicBlock* block); void Assemble(NativeCodeBasicBlock* block);
void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps); void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps);
bool IsUsedResultInstructions(NumberSet& requiredTemps); bool IsUsedResultInstructions(NumberSet& requiredTemps);
bool BitFieldForwarding(NativeRegisterDataSet& data, AsmInsType& carryop);
bool ValueForwarding(NativeRegisterDataSet& data, AsmInsType & carryop, bool initial, bool final); bool ValueForwarding(NativeRegisterDataSet& data, AsmInsType & carryop, bool initial, bool final);
void Simulate(NativeRegisterDataSet& data); void Simulate(NativeRegisterDataSet& data);
@ -241,6 +246,7 @@ public:
bool MoveIndirectLoadStoreUp(int at); bool MoveIndirectLoadStoreUp(int at);
bool MoveAbsoluteLoadStoreUp(int at); bool MoveAbsoluteLoadStoreUp(int at);
bool MoveLoadStoreOutOfXYRangeUp(int at); bool MoveLoadStoreOutOfXYRangeUp(int at);
bool MoveLoadIndirectTempStoreUp(int at);
bool MoveLoadAddImmStoreAbsXUp(int at); bool MoveLoadAddImmStoreAbsXUp(int at);
bool MoveStaTaxLdaStaDown(int at); bool MoveStaTaxLdaStaDown(int at);
@ -289,6 +295,7 @@ public:
bool ReverseReplaceTAX(int at); bool ReverseReplaceTAX(int at);
bool ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final); bool ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final);
bool BitFieldForwarding(const NativeRegisterDataSet& data);
void CollectEntryBlocks(NativeCodeBasicBlock* block); 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) bool SourceFile::ReadLineRLE(char* line)
{ {
assert(mFill >= 0 && mFill < 256); assert(mFill >= 0 && mFill < 256);
@ -171,6 +261,10 @@ bool SourceFile::ReadLine(char* line)
if (ReadLineRLE(line)) if (ReadLineRLE(line))
return true; return true;
break; break;
case SFM_BINARY_LZO:
if (ReadLineLZO(line))
return true;
break;
} }
fclose(mFile); fclose(mFile);
@ -233,6 +327,7 @@ bool SourceFile::Open(const char* name, const char* path, SourceFileMode mode)
mMode = mode; mMode = mode;
mLimit = 0x10000; mLimit = 0x10000;
mFill = 0; mFill = 0;
mPos = 0;
return true; return true;
} }

View File

@ -18,7 +18,8 @@ enum SourceFileMode
{ {
SFM_TEXT, SFM_TEXT,
SFM_BINARY, SFM_BINARY,
SFM_BINARY_RLE SFM_BINARY_RLE,
SFM_BINARY_LZO
}; };
class SourceFile class SourceFile
{ {
@ -31,12 +32,13 @@ public:
SourceFileMode mMode; SourceFileMode mMode;
int mLimit; int mLimit;
char mBuffer[256]; char mBuffer[512];
int mFill; int mFill, mPos;
bool ReadLine(char* line); bool ReadLine(char* line);
bool ReadLineRLE(char* line); bool ReadLineRLE(char* line);
bool ReadLineLZO(char* line);
SourceFile(void); SourceFile(void);
~SourceFile(void); ~SourceFile(void);

View File

@ -656,6 +656,8 @@ void Scanner::NextToken(void)
{ {
if (!strcmp(mTokenIdent->mString, "rle")) if (!strcmp(mTokenIdent->mString, "rle"))
mode = SFM_BINARY_RLE; mode = SFM_BINARY_RLE;
else if (!strcmp(mTokenIdent->mString, "lzo"))
mode = SFM_BINARY_LZO;
else else
mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Invalid embed compression mode", mTokenIdent); 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 #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.5.121"); strcpy(strProductVersion, "1.6.123");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

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

View File

@ -130,6 +130,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_24F2466589154E2DAA108C2EDB3BB432"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_29ED5D9B606D45DA80CFF329A7643DC8" "MsmKey" = "8:_29ED5D9B606D45DA80CFF329A7643DC8"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -274,6 +280,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_557F7BC3AD794C4A93D5DFDA00024E1B"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_5832EB4DC2134FF0BB7872666547CA0B" "MsmKey" = "8:_5832EB4DC2134FF0BB7872666547CA0B"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -664,6 +676,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_CA8FE59769D748A5BF04ABC3F9154DBA"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_CC473A7B399D4B31A9DC8C94F7771EF7" "MsmKey" = "8:_CC473A7B399D4B31A9DC8C94F7771EF7"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -1327,6 +1345,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "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" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29ED5D9B606D45DA80CFF329A7643DC8"
{ {
"SourcePath" = "8:..\\samples\\kernalio\\diskdir.c" "SourcePath" = "8:..\\samples\\kernalio\\diskdir.c"
@ -1807,6 +1845,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "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" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5832EB4DC2134FF0BB7872666547CA0B"
{ {
"SourcePath" = "8:..\\samples\\sprites\\make.bat" "SourcePath" = "8:..\\samples\\sprites\\make.bat"
@ -3107,6 +3165,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "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" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CC473A7B399D4B31A9DC8C94F7771EF7"
{ {
"SourcePath" = "8:..\\samples\\memmap\\charsethi.c" "SourcePath" = "8:..\\samples\\memmap\\charsethi.c"
@ -4023,15 +4101,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{9712E64F-8FDC-4FD2-BE20-8889E458BC89}" "ProductCode" = "8:{F66E2274-2B16-49B2-950F-83A3DC2EEA9D}"
"PackageCode" = "8:{63C93E1F-200E-43F4-8A18-C9A7743F2543}" "PackageCode" = "8:{4F43842C-6F90-403A-8CE1-352F775F975F}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.5.121" "ProductVersion" = "8:1.6.123"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"
@ -4545,7 +4623,7 @@
{ {
"{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6" "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6"
{ {
"SourcePath" = "8:..\\Debug\\oscar64.exe" "SourcePath" = "8:..\\Release\\oscar64.exe"
"TargetName" = "8:" "TargetName" = "8:"
"Tag" = "8:" "Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4" "Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"

View File

@ -4,6 +4,7 @@
../../bin/oscar64 charsetlo.c ../../bin/oscar64 charsetlo.c
../../bin/oscar64 charsethi.c ../../bin/oscar64 charsethi.c
../../bin/oscar64 charsetcopy.c ../../bin/oscar64 charsetcopy.c
../../bin/oscar64 charsetexpand.c
../../bin/oscar64 easyflash.c -n -tf=crt ../../bin/oscar64 easyflash.c -n -tf=crt
../../bin/oscar64 easyflashreloc.c -n -tf=crt ../../bin/oscar64 easyflashreloc.c -n -tf=crt
../../bin/oscar64 easyflashshared.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 charsetlo.c
call ..\..\bin\oscar64 charsethi.c call ..\..\bin\oscar64 charsethi.c
call ..\..\bin\oscar64 charsetcopy.c call ..\..\bin\oscar64 charsetcopy.c
call ..\..\bin\oscar64 charsetexpand.c
call ..\..\bin\oscar64 easyflash.c -n -tf=crt call ..\..\bin\oscar64 easyflash.c -n -tf=crt
call ..\..\bin\oscar64 easyflashreloc.c -n -tf=crt call ..\..\bin\oscar64 easyflashreloc.c -n -tf=crt
call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt