Resolve merge conflicts

This commit is contained in:
Lucas Scharenbroich 2018-04-15 13:52:55 -05:00
parent 05b56603f1
commit 28db7072d0
2 changed files with 170 additions and 49 deletions

View File

@ -11,13 +11,18 @@ namespace SpriteCompiler.Problem
/// </summary>
public abstract class CodeSequence
{
protected CodeSequence()
: this(0)
{
}
protected CodeSequence(int cycles)
{
CycleCount = cycles;
}
// Number of cycles that this code snippets takes to execute
public int CycleCount { get; private set; }
public int CycleCount { get; protected set; }
// Function to generate a new state based on the code's operation
public abstract SpriteGeneratorState Apply(SpriteGeneratorState state);
@ -200,6 +205,40 @@ namespace SpriteCompiler.Problem
}
}
public sealed class EIGHT_BIT_STORE : CodeSequence
{
private SpriteByte data;
public EIGHT_BIT_STORE(SpriteByte data)
{
this.data = data;
}
public override SpriteGeneratorState Apply(SpriteGeneratorState state)
{
var offset = data.Offset - state.S.Value;
// If
return state.Clone(_ =>
{
_.A = Register.UNINITIALIZED;
_.RemoveByte((ushort)(offset + _.S.Value));
});
}
public override string Emit()
{
return String.Join("\n",
FormatLine("", "LDA", offset.ToString("X2") + ",s", "4 cycles"),
FormatLine("", "AND", "#$" + mask.ToString("X2"), "2 cycles"),
FormatLine("", "ORA", "#$" + value.ToString("X2"), "2 cycles"),
FormatLine("", "STA", offset.ToString("X2") + ",s", "4 cycles")
);
}
}
public sealed class STACK_REL_8_BIT_READ_MODIFY_WRITE : CodeSequence
{
private readonly byte value;

View File

@ -6,8 +6,55 @@
using System.Collections.Generic;
using System.Linq;
public sealed class SolidRun
{
private readonly SpriteByte first;
private readonly SpriteByte last;
public SolidRun(SpriteByte first, SpriteByte last)
{
this.first = first;
this.last = last;
}
public SpriteByte First { get { return first; } }
public SpriteByte Last { get { return last; } }
public int Count { get { return last.Offset - first.Offset + 1; } }
}
public static class StateHelpers
{
public static SolidRun FirstSolidRun(IEnumerable<SpriteByte> open)
{
bool trigger = false;
SpriteByte first = default(SpriteByte);
SpriteByte last = default(SpriteByte);
foreach (var item in open)
{
if (item.Mask == 0x00 && !trigger)
{
first = item;
trigger = true;
}
if ((item.Mask != 0x00 || (item.Offset - last.Offset) > 1) && trigger)
{
return new SolidRun(first, last);
}
last = item;
}
// If we get to the end and are still solid, great
if (last.Mask == 0x00 && trigger)
{
return new SolidRun(first, last);
}
return null;
}
public static SpriteByte? TryGetStackByte(this SpriteGeneratorState state, IDictionary<ushort, SpriteByte> data)
{
SpriteByte top;
@ -74,6 +121,88 @@
}
}
/// <summary>
/// A collection of successor function that deal with very specific situations. A full successor function can
/// be composed of these functions
/// </summary>
public static class SuccessorFunctions
{
/// <summary>
/// Proposed actions to move the stack. We can only move the stack if we are in 16-bit accumulator
/// mode.
///
/// We only consider two movements (add to this list if suboptimal code sequences are found)
///
/// 1. Jump to first byte more than 256 bytes ahead of the current stack location
/// 2. Jump to the last byte of the nearest run
/// </summary>
public sealed class StackMove : ISuccessorFunction<CodeSequence, SpriteGeneratorState>
{
public IEnumerable<Tuple<CodeSequence, SpriteGeneratorState>> Successors(SpriteGeneratorState state)
{
if (!state.LongA || !state.S.IsScreenOffset)
{
yield break;
}
var openList = state.RemainingBytes();
// Check for the first byte more than 255 bytes beyound our current location
var nextByte = openList.Where(sb => (sb.Offset - state.S.Value) > 255).Cast<SpriteByte?>().FirstOrDefault();
if (nextByte != null)
{
yield return state.Apply(new MOVE_STACK(nextByte.Value.Offset - state.S.Value));
}
// Check for the next run of solid bytes and move to the end
var run = StateHelpers.FirstSolidRun(openList);
if (run != null)
{
yield return state.Apply(new MOVE_STACK(run.Last.Offset - state.S.Value));
}
yield break;
}
}
/// <summary>
/// Write the next 8-bit value that is not a solid byte. Must already be in 8-bit mode
/// </summary>
public sealed class EighBitMixed : ISuccessorFunction<CodeSequence, SpriteGeneratorState>
{
public IEnumerable<Tuple<CodeSequence, SpriteGeneratorState>> Successors(SpriteGeneratorState state)
{
if (state.LongA || !state.S.IsScreenOffset)
{
yield break;
}
var openList = state.RemainingBytes();
// Get the first byte with a non-zero mask that is within 255 bytes of the current location
var nextByte = openList.Where(sb => (sb.Offset - state.S.Value) <= 255).Cast<SpriteByte?>().FirstOrDefault();
if (nextByte != null)
{
yield return state.Apply(new MOVE_STACK(nextByte.Value.Offset - state.S.Value));
}
// Check for the next run of solid bytes and move to the end
var run = StateHelpers.FirstSolidRun(openList);
if (run != null)
{
yield return state.Apply(new MOVE_STACK(run.Last.Offset - state.S.Value));
}
yield break;
}
}
}
/// <summary>
/// This successor function does not try to leverage cached values in the X, Y or D registers
/// </summary>
public sealed class SpriteGeneratorSuccessorFunction : ISuccessorFunction<CodeSequence, SpriteGeneratorState>
{
public IEnumerable<Tuple<CodeSequence, SpriteGeneratorState>> Successors(SpriteGeneratorState state)
@ -94,7 +223,7 @@
var firstByte = open.First();
// Identify the first run of solid bytes
var firstSolid = FirstSolidRun(open);
var firstSolid = StateHelpers.FirstSolidRun(open);
// In an initial state, the stack has not been set, but the accumulator contains a screen
// offset address. There are three possible options
@ -316,53 +445,6 @@
pair.Item2.Mask == 0x00;
}
private class SolidRun
{
private readonly SpriteByte first;
private readonly SpriteByte last;
public SolidRun(SpriteByte first, SpriteByte last)
{
this.first = first;
this.last = last;
}
public SpriteByte First { get { return first; } }
public SpriteByte Last { get { return last; } }
public int Count { get { return last.Offset - first.Offset + 1; } }
}
private SolidRun FirstSolidRun(IEnumerable<SpriteByte> open)
{
bool trigger = false;
SpriteByte first = default(SpriteByte);
SpriteByte last = default(SpriteByte);
foreach (var item in open)
{
if (item.Mask == 0x00 && !trigger)
{
first = item;
trigger = true;
}
if ((item.Mask != 0x00 || (item.Offset - last.Offset) > 1) && trigger)
{
return new SolidRun(first, last);
}
last = item;
}
// If we get to the end and are still sold, great
if (last.Mask == 0x00 && trigger)
{
return new SolidRun(first, last);
}
return null;
}
private Func<SpriteByte, bool> WithinRangeOf(int addr, int range)
{
return x => (x.Offset >= addr) && ((x.Offset - addr) < range);