mirror of
https://github.com/edmccard/twoapple-reboot.git
synced 2024-08-31 15:29:08 +00:00
New timer code
This commit is contained in:
parent
22f4327c0d
commit
bf117ac730
@ -96,12 +96,12 @@ class Paddles
|
||||
if (onTrigger[i] == 0) onTrigger[i] = 1;
|
||||
switchVal[i] = 0x80;
|
||||
}
|
||||
timer.new Counter(onTrigger[0], &pdl_0_expired);
|
||||
timer.new Counter(onTrigger[1], &pdl_1_expired);
|
||||
timer.addCounter(onTrigger[0], &pdl_0_expired);
|
||||
timer.addCounter(onTrigger[1], &pdl_1_expired);
|
||||
if (numPaddles > 2)
|
||||
{
|
||||
timer.new Counter(onTrigger[2], &pdl_2_expired);
|
||||
timer.new Counter(onTrigger[3], &pdl_3_expired);
|
||||
timer.addCounter(onTrigger[2], &pdl_2_expired);
|
||||
timer.addCounter(onTrigger[3], &pdl_3_expired);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,8 +103,8 @@ class Speaker
|
||||
|
||||
void update()
|
||||
{
|
||||
uint elapsedSinceToggle = cycle.currentVal() - lastToggleTick;
|
||||
lastToggleTick = cycle.currentVal();
|
||||
uint elapsedSinceToggle = cycle.val() - lastToggleTick;
|
||||
lastToggleTick = cycle.val();
|
||||
elapsedSinceToggle = processExtraBuffer(elapsedSinceToggle);
|
||||
|
||||
uint samples = elapsedSinceToggle / sampleTicks;
|
||||
|
@ -70,28 +70,34 @@ ubyte[256] controllerRom = [
|
||||
class StopTimer
|
||||
{
|
||||
Timer timer;
|
||||
Timer.Counter stopCounter;
|
||||
bool stopCounter;
|
||||
void delegate() notifyExpired;
|
||||
ulong t_tick;
|
||||
size_t t_idx;
|
||||
|
||||
void startCountdown()
|
||||
{
|
||||
if (stopCounter is null)
|
||||
stopCounter = timer.new Counter(1_020_484, &expire);
|
||||
if (!stopCounter)
|
||||
{
|
||||
t_idx = timer.addCounter(1_020_484, &expire);
|
||||
t_tick = timer.totalTicks;
|
||||
stopCounter = true;
|
||||
}
|
||||
}
|
||||
|
||||
void stopCountdown()
|
||||
{
|
||||
if (stopCounter !is null)
|
||||
if (stopCounter)
|
||||
{
|
||||
stopCounter.discard();
|
||||
stopCounter = null;
|
||||
timer.removeCounter(t_tick, t_idx);
|
||||
stopCounter = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool expire()
|
||||
{
|
||||
notifyExpired();
|
||||
stopCounter = null;
|
||||
stopCounter = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -40,17 +40,15 @@ import ioummu;
|
||||
class SystemBase
|
||||
{
|
||||
Video video_;
|
||||
Timer timer;
|
||||
|
||||
abstract void reboot();
|
||||
abstract void reset();
|
||||
abstract uint checkpoint();
|
||||
abstract uint sinceCheckpoint(uint cp);
|
||||
abstract void execute();
|
||||
}
|
||||
|
||||
class System(string chip) : SystemBase
|
||||
{
|
||||
Timer timer;
|
||||
Timer.Cycle deviceCycle;
|
||||
AddressDecoder decoder;
|
||||
SoftSwitchPage switches;
|
||||
@ -138,9 +136,9 @@ class System(string chip) : SystemBase
|
||||
void initTimer()
|
||||
{
|
||||
// XXX constants? variables?
|
||||
timer = new Timer(10_205, 1_020_484);
|
||||
timer = new Timer(10_205, 1_020_484, &primaryStop);
|
||||
deviceCycle =
|
||||
timer.startCycle(timer.primaryCounter.startLength * 2);
|
||||
timer.new Cycle(timer.primaryLength * 2);
|
||||
}
|
||||
|
||||
void initMemory(ubyte[] romDump)
|
||||
@ -177,7 +175,7 @@ class System(string chip) : SystemBase
|
||||
resetLow = &cpu.resetLow;
|
||||
|
||||
debug(disassemble) cpu.memoryName = &decoder.memoryReadName;
|
||||
timer.onPrimaryStop(&primaryStop);
|
||||
// timer.onPrimaryStop(&primaryStop);
|
||||
}
|
||||
|
||||
void initIO(ubyte[] vidRom)
|
||||
@ -218,18 +216,6 @@ class System(string chip) : SystemBase
|
||||
*resetLow = true;
|
||||
}
|
||||
|
||||
override uint checkpoint()
|
||||
{
|
||||
return timer.primaryCounter.currentLength;
|
||||
}
|
||||
|
||||
override uint sinceCheckpoint(uint cp)
|
||||
{
|
||||
uint currentLength = timer.primaryCounter.currentLength;
|
||||
return ((currentLength == timer.primaryCounter.startLength) ?
|
||||
cp : (cp - currentLength));
|
||||
}
|
||||
|
||||
override void execute()
|
||||
{
|
||||
cpu.run(true);
|
||||
|
460
src/timer.d
460
src/timer.d
@ -1,7 +1,7 @@
|
||||
/+
|
||||
+ timer.d
|
||||
+
|
||||
+ Copyright: 2007 Gerald Stocker
|
||||
+ Copyright: 2012 Ed McCardell, 2007 Gerald Stocker
|
||||
+
|
||||
+ This file is part of twoapple-reboot.
|
||||
+
|
||||
@ -22,222 +22,318 @@
|
||||
|
||||
module timer;
|
||||
|
||||
class Timer
|
||||
final class Timer
|
||||
{
|
||||
class Cycle
|
||||
{
|
||||
int delta;
|
||||
uint rollOver;
|
||||
|
||||
this(uint maxVal)
|
||||
{
|
||||
rollOver = maxVal;
|
||||
restart();
|
||||
}
|
||||
|
||||
void restart()
|
||||
{
|
||||
delta = 0 - currentCounter.elapsed();
|
||||
}
|
||||
|
||||
uint currentVal()
|
||||
{
|
||||
return (currentCounter.elapsed() + delta) % rollOver;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
delta = currentVal();
|
||||
}
|
||||
}
|
||||
|
||||
class Counter
|
||||
private:
|
||||
static struct Counter
|
||||
{
|
||||
uint start, curr;
|
||||
bool active;
|
||||
size_t next = -1, nextFree;
|
||||
bool delegate() expiry;
|
||||
uint startLength, currentLength;
|
||||
int ticks;
|
||||
bool shouldContinue;
|
||||
ulong creationTick;
|
||||
|
||||
this(uint start)
|
||||
this(uint length, bool delegate() expiry, ulong creationTick)
|
||||
{
|
||||
shouldContinue = true;
|
||||
startLength = currentLength = ticks = start;
|
||||
addCounter(this);
|
||||
start = curr = length;
|
||||
this.expiry = expiry;
|
||||
this.creationTick = creationTick;
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
|
||||
this(uint start, bool delegate() expiration)
|
||||
ulong _totalTicks;
|
||||
uint start = uint.max, curr = uint.max, minCurr = uint.max;
|
||||
uint balance;
|
||||
size_t head, tail, nextFree;
|
||||
Counter[] counters;
|
||||
uint _hertz;
|
||||
|
||||
final void setNextFree()
|
||||
{
|
||||
this(start);
|
||||
initCounter(this);
|
||||
expiry = expiration;
|
||||
for (size_t i = nextFree; i < counters.length; i++)
|
||||
counters[i].nextFree = i + 1;
|
||||
}
|
||||
|
||||
final uint elapsed()
|
||||
final void deleteCounter(size_t idx, size_t prev)
|
||||
{
|
||||
return currentLength - ticks;
|
||||
auto tmp = nextFree;
|
||||
nextFree = idx;
|
||||
counters[idx].nextFree = tmp;
|
||||
|
||||
auto next = counters[idx].next;
|
||||
if (idx == head)
|
||||
{
|
||||
head = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
counters[prev].next = next;
|
||||
}
|
||||
if (idx == tail)
|
||||
{
|
||||
tail = prev;
|
||||
counters[tail].next = -1;
|
||||
}
|
||||
|
||||
counters[idx].active = false;
|
||||
}
|
||||
|
||||
public:
|
||||
this(uint primaryLength, uint hertz, bool delegate() primaryStop)
|
||||
{
|
||||
counters = new Counter[50];
|
||||
setNextFree();
|
||||
_hertz = hertz;
|
||||
addCounter(primaryLength, primaryStop);
|
||||
}
|
||||
|
||||
final @property uint primaryRemaining()
|
||||
{
|
||||
return counters[0].curr;
|
||||
}
|
||||
|
||||
final @property uint primaryLength()
|
||||
{
|
||||
return counters[0].start;
|
||||
}
|
||||
|
||||
final @property uint hertz()
|
||||
{
|
||||
return _hertz;
|
||||
}
|
||||
|
||||
final @property ulong totalTicks()
|
||||
{
|
||||
return _totalTicks;
|
||||
}
|
||||
|
||||
final void tick()
|
||||
{
|
||||
--ticks;
|
||||
if (ticks == 0)
|
||||
_totalTicks++;
|
||||
curr--;
|
||||
if (!curr)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
final void forceExpire()
|
||||
minCurr = uint.max;
|
||||
size_t idx = head;
|
||||
size_t prev = -1;
|
||||
while (idx != -1)
|
||||
{
|
||||
ticks = 1;
|
||||
tick();
|
||||
}
|
||||
|
||||
final void discard()
|
||||
if (counters[idx].active)
|
||||
{
|
||||
expiry = &nullExpiry;
|
||||
forceExpire();
|
||||
}
|
||||
|
||||
private final void resume()
|
||||
counters[idx].curr -= start;
|
||||
if (counters[idx].curr) counters[idx].curr -= balance;
|
||||
if (!counters[idx].curr)
|
||||
{
|
||||
currentLength = ticks;
|
||||
if (counters[idx].expiry())
|
||||
counters[idx].curr = counters[idx].start;
|
||||
else
|
||||
deleteCounter(idx, prev);
|
||||
}
|
||||
|
||||
private final bool expire()
|
||||
{
|
||||
ticks = currentLength = startLength;
|
||||
return expiry();
|
||||
}
|
||||
|
||||
private bool nullExpiry() { return false; }
|
||||
}
|
||||
|
||||
class DelayedCounter : Counter
|
||||
{
|
||||
uint realStart;
|
||||
bool delegate() realExpiry;
|
||||
|
||||
this(uint start, bool delegate() expiration, uint delay)
|
||||
{
|
||||
realStart = start;
|
||||
realExpiry = expiration;
|
||||
super(delay, &becomeReal);
|
||||
}
|
||||
|
||||
private bool becomeReal()
|
||||
{
|
||||
ticks = currentLength = startLength = realStart;
|
||||
expiry = realExpiry;
|
||||
bool retval = expiry();
|
||||
initCounter(this);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
Cycle[] cycles;
|
||||
Counter[] counters;
|
||||
Counter primaryCounter, currentCounter;
|
||||
uint hertz;
|
||||
|
||||
this(uint primaryStart, uint hz)
|
||||
{
|
||||
hertz = hz;
|
||||
cycles.length = 10;
|
||||
counters.length = 10;
|
||||
cycles.length = 0;
|
||||
counters.length = 0;
|
||||
currentCounter = primaryCounter = new Counter(primaryStart);
|
||||
}
|
||||
|
||||
final void onPrimaryStop(bool delegate() expiration)
|
||||
{
|
||||
primaryCounter.expiry = expiration;
|
||||
}
|
||||
|
||||
Cycle startCycle(uint maxVal)
|
||||
{
|
||||
cycles.length = cycles.length + 1;
|
||||
cycles[$-1] = new Cycle(maxVal);
|
||||
return cycles[$-1];
|
||||
}
|
||||
|
||||
void tick()
|
||||
{
|
||||
currentCounter.tick();
|
||||
}
|
||||
|
||||
private void deleteCounters()
|
||||
{
|
||||
int numCounters = cast(int)counters.length;
|
||||
int lastCounter;
|
||||
main: for (int counter = 0; counter < counters.length; ++counter)
|
||||
{
|
||||
lastCounter = counter;
|
||||
while (!counters[counter].shouldContinue)
|
||||
{
|
||||
numCounters--;
|
||||
if (++counter >= counters.length) break main;
|
||||
}
|
||||
currentCounter = counters[lastCounter] = counters[counter];
|
||||
}
|
||||
if (numCounters < counters.length)
|
||||
{
|
||||
counters.length = numCounters;
|
||||
}
|
||||
}
|
||||
|
||||
private void addCounter(Counter newCounter)
|
||||
{
|
||||
counters.length = counters.length + 1;
|
||||
counters[$-1] = newCounter;
|
||||
}
|
||||
|
||||
private void initCounter(Counter newCounter)
|
||||
{
|
||||
if (newCounter.ticks < currentCounter.ticks)
|
||||
{
|
||||
reset(newCounter);
|
||||
if (counters[idx].active && counters[idx].curr < minCurr)
|
||||
minCurr = counters[idx].curr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newCounter.ticks += currentCounter.elapsed();
|
||||
deleteCounter(idx, prev);
|
||||
}
|
||||
prev = idx;
|
||||
idx = counters[idx].next;
|
||||
}
|
||||
start = curr = minCurr;
|
||||
balance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void reset(Counter newCounter = null)
|
||||
final size_t addCounter(uint length, bool delegate() expiry)
|
||||
{
|
||||
// update cycle counts
|
||||
for (int cycle = 0; cycle < cycles.length; ++cycle)
|
||||
if (nextFree == counters.length)
|
||||
{
|
||||
cycles[cycle].update();
|
||||
counters.length += 20;
|
||||
setNextFree();
|
||||
}
|
||||
|
||||
// update counter counts
|
||||
for (int counter = 0; counter < counters.length; ++counter)
|
||||
{
|
||||
if (counters[counter] !is currentCounter &&
|
||||
counters[counter] !is newCounter)
|
||||
counters[counter].ticks -= currentCounter.elapsed();
|
||||
}
|
||||
auto idx = nextFree;
|
||||
nextFree = counters[nextFree].nextFree;
|
||||
counters[idx] = Counter(length, expiry, _totalTicks);
|
||||
counters[tail].next = idx;
|
||||
tail = idx;
|
||||
counters[tail].next = -1;
|
||||
|
||||
// check for expired counters
|
||||
for (int counter = 0; counter < counters.length; ++counter)
|
||||
if (curr == 0)
|
||||
{
|
||||
if (counters[counter].ticks <= 0)
|
||||
counters[counter].shouldContinue = counters[counter].expire();
|
||||
counters[idx].curr += start;
|
||||
}
|
||||
else
|
||||
counters[counter].resume();
|
||||
}
|
||||
|
||||
//delete counters that should be deleted
|
||||
deleteCounters();
|
||||
|
||||
// set current counter
|
||||
for (int counter = 0; counter < counters.length; ++counter)
|
||||
{
|
||||
if (counters[counter].ticks < currentCounter.ticks)
|
||||
currentCounter = counters[counter];
|
||||
if (counters[idx].curr < curr)
|
||||
{
|
||||
balance = start - curr;
|
||||
start = curr = counters[idx].curr;
|
||||
}
|
||||
else
|
||||
{
|
||||
counters[idx].curr += (start - curr);
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
final void removeCounter(ulong creationTick, size_t idx)
|
||||
{
|
||||
assert(counters[idx].creationTick == creationTick);
|
||||
counters[idx].active = false;
|
||||
}
|
||||
|
||||
|
||||
final class Cycle
|
||||
{
|
||||
ulong startTick;
|
||||
uint rollOver;
|
||||
|
||||
this(uint rollOver)
|
||||
{
|
||||
this.rollOver = rollOver;
|
||||
restart();
|
||||
}
|
||||
|
||||
final void restart()
|
||||
{
|
||||
startTick = _totalTicks;
|
||||
}
|
||||
|
||||
final uint val()
|
||||
{
|
||||
return (_totalTicks - startTick) % rollOver;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
bool primary() { return true; }
|
||||
|
||||
auto t = new Timer(10205, 1020484, &primary);
|
||||
int c1 = 0, c2 = 0;
|
||||
t.addCounter(10, (){assert(t._totalTicks == 10); c1++; return true;});
|
||||
foreach (i; 0..9) t.tick();
|
||||
t.addCounter(5, (){assert(t._totalTicks == 14); c2++; return true;});
|
||||
foreach (i; 0..5) t.tick();
|
||||
assert (c1 == 1 && c2 == 1);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
bool primary() { return true; }
|
||||
|
||||
auto t = new Timer(10205, 1020484, &primary);
|
||||
int c1 = 0, c2 = 0;
|
||||
struct Dummy
|
||||
{
|
||||
bool exp1()
|
||||
{
|
||||
auto ticks = t._totalTicks;
|
||||
assert((c1 == 0 && ticks == 10) || (c1 == 1 && ticks == 30));
|
||||
c1++;
|
||||
t.addCounter(10, &exp2);
|
||||
return false;
|
||||
}
|
||||
bool exp2()
|
||||
{
|
||||
auto ticks = t._totalTicks;
|
||||
assert((c2 == 0 && ticks == 20) || (c2 == 1 && ticks == 40));
|
||||
c2++;
|
||||
t.addCounter(10, &exp1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Dummy d;
|
||||
t.addCounter(10, &d.exp1);
|
||||
foreach (i; 0..40) t.tick();
|
||||
assert(c1 == 2 && c2 == 2);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
bool primary() { return true; }
|
||||
|
||||
auto t = new Timer(10205, 1020484, &primary);
|
||||
int c1 = 0, c2 = 0, c3 = 0;
|
||||
|
||||
void addExtra()
|
||||
{
|
||||
t.addCounter(4, (){auto ticks = t._totalTicks;
|
||||
assert((c1 == 0 && ticks == 14) ||
|
||||
(c1 == 1 && ticks == 24));
|
||||
c1++;
|
||||
return false;});
|
||||
t.addCounter(5, (){auto ticks = t._totalTicks;
|
||||
assert((c2 == 0 && ticks == 15) ||
|
||||
(c2 == 1 && ticks == 25));
|
||||
c2++;
|
||||
return false;});
|
||||
t.addCounter(6, (){auto ticks = t._totalTicks;
|
||||
assert((c3 == 0 && ticks == 16) ||
|
||||
(c3 == 1 && ticks == 26));
|
||||
c3++;
|
||||
return false;});
|
||||
}
|
||||
t.addCounter(10, (){addExtra(); return true;});
|
||||
foreach (i; 0..30) t.tick();
|
||||
assert (c1 == 2 && c2 == 2 && c3 == 2);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
bool primary() { return true; }
|
||||
|
||||
auto t = new Timer(10205, 1020484, &primary);
|
||||
auto c1 = t.addCounter(10, (){assert(false); return false;});
|
||||
auto c1_tick = t._totalTicks;
|
||||
foreach (i; 0..5) t.tick();
|
||||
t.removeCounter(c1_tick, c1);
|
||||
foreach (i; 0..5) t.tick();
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
bool primary() { return true; }
|
||||
|
||||
auto t = new Timer(10205, 1020484, &primary);
|
||||
int c1 = 0, c2 = 0;
|
||||
t.addCounter(10, (){c1++; return true;});
|
||||
auto idx = t.addCounter(15, (){c2++; return true;});
|
||||
auto tick = t._totalTicks;
|
||||
foreach (i; 0..20) t.tick();
|
||||
assert(c1 == 2 && c2 == 1);
|
||||
t.removeCounter(tick, idx);
|
||||
foreach (i; 0..20) t.tick();
|
||||
assert(c1 == 4 && c2 == 1);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
bool primary() { return true; }
|
||||
|
||||
auto t = new Timer(10205, 1020484, &primary);
|
||||
|
||||
bool t1() { assert(!(t.totalTicks % 5000)); return true; }
|
||||
bool t2() { assert(!(t.totalTicks % 4500)); return true; }
|
||||
bool t3() { assert(!(t.totalTicks % 6500)); return true; }
|
||||
bool junk() { assert(!((t.totalTicks - 7000) % 1500)); return true; }
|
||||
|
||||
t.addCounter(5000, &t1);
|
||||
t.addCounter(4500, &t2);
|
||||
t.addCounter(6500, &t3);
|
||||
|
||||
foreach (i; 0..7000) t.tick();
|
||||
|
||||
t.addCounter(1500, &junk);
|
||||
t.addCounter(1500, &junk);
|
||||
t.addCounter(1500, &junk);
|
||||
t.addCounter(1500, &junk);
|
||||
|
||||
foreach (i; 0..7000) t.tick();
|
||||
}
|
||||
|
@ -210,6 +210,8 @@ class Input
|
||||
|
||||
void onJoystickEvent()
|
||||
{
|
||||
import std.stdio;
|
||||
writeln("QWERTY joyevent");
|
||||
static const float scale = 65535.0 / 2760.0;
|
||||
static const int shift = 32768;
|
||||
bool buttonDown = false;
|
||||
|
@ -143,6 +143,13 @@ class TwoappleMainWindow : MainWindow
|
||||
return super.windowDelete(event, widget);
|
||||
}
|
||||
|
||||
uint sinceCheckpoint(uint cp)
|
||||
{
|
||||
uint currentLength = system.timer.primaryRemaining;
|
||||
return ((currentLength == system.timer.primaryLength) ?
|
||||
cp : (cp - currentLength));
|
||||
}
|
||||
|
||||
bool configChanged;
|
||||
bool runOnce;
|
||||
bool stayOpen;
|
||||
@ -189,9 +196,9 @@ class TwoappleMainWindow : MainWindow
|
||||
|
||||
if (shouldRun)
|
||||
{
|
||||
willElapse = system.checkpoint();
|
||||
willElapse = system.timer.primaryRemaining;
|
||||
system.execute();
|
||||
didElapse = system.sinceCheckpoint(willElapse);
|
||||
didElapse = sinceCheckpoint(willElapse);
|
||||
input.processEvents();
|
||||
// XXX do something about typeahead?
|
||||
if (!runOnce)
|
||||
|
@ -222,7 +222,7 @@ class TextPatternGenerator_II : TextPatternGenerator
|
||||
// XXX XXX INIT
|
||||
void init(Timer timer)
|
||||
{
|
||||
timer.new Counter(timer.hertz / 2, &toggleFlash);
|
||||
timer.addCounter(timer.hertz / 2, &toggleFlash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +307,7 @@ class TextPatternGenerator_IIe : TextPatternGenerator
|
||||
// XXX XXX INIT
|
||||
void init(Timer timer)
|
||||
{
|
||||
timer.new Counter(32 * 262 * 65, &toggleFlash); // XXX PAL
|
||||
timer.addCounter(32 * 262 * 65, &toggleFlash); // XXX PAL
|
||||
}
|
||||
|
||||
void altCharsetOn()
|
||||
|
@ -28,12 +28,14 @@ import memory;
|
||||
import timer;
|
||||
import device.base;
|
||||
|
||||
|
||||
class Scanner : ScannerBase
|
||||
{
|
||||
uint page;
|
||||
bool graphicsTime, textSwitch, mixedSwitch, hiresSwitch, oldTextSwitch;
|
||||
Mode mode;
|
||||
|
||||
Timer timer;
|
||||
Timer.Cycle vidCycle;
|
||||
uint frameSkip, frameCount;
|
||||
|
||||
@ -47,14 +49,23 @@ class Scanner : ScannerBase
|
||||
void init(Timer timer)
|
||||
{
|
||||
int frameLen = 262 * 65; // XXX PAL: 312 * 65
|
||||
vidCycle = timer.startCycle(frameLen);
|
||||
this.timer = timer;
|
||||
vidCycle = timer.new Cycle(frameLen);
|
||||
graphicsTime = true;
|
||||
|
||||
timer.new Counter(frameLen, &graphicsTimeOn);
|
||||
timer.new DelayedCounter(frameLen, &frameComplete, frameLen - 1);
|
||||
timer.new DelayedCounter(frameLen, &graphicsTimeOff, 160 * 65);
|
||||
timer.new DelayedCounter(frameLen, &graphicsTimeOn, 192 * 65);
|
||||
timer.new DelayedCounter(frameLen, &graphicsTimeOff, 224 * 65);
|
||||
timer.addCounter(frameLen, &graphicsTimeOn);
|
||||
timer.addCounter(frameLen - 1,
|
||||
(){frameComplete();
|
||||
timer.addCounter(frameLen, &frameComplete); return false;});
|
||||
timer.addCounter(160 * 65,
|
||||
(){graphicsTimeOff();
|
||||
timer.addCounter(frameLen, &graphicsTimeOff); return false;});
|
||||
timer.addCounter(192 * 65,
|
||||
(){graphicsTimeOn();
|
||||
timer.addCounter(frameLen, &graphicsTimeOn); return false;});
|
||||
timer.addCounter(224 * 65,
|
||||
(){graphicsTimeOff();
|
||||
timer.addCounter(frameLen, &graphicsTimeOff); return false;});
|
||||
}
|
||||
|
||||
void forceFrame()
|
||||
@ -199,12 +210,12 @@ class Scanner : ScannerBase
|
||||
|
||||
uint currentLine()
|
||||
{
|
||||
return vidCycle.currentVal() / 65;
|
||||
return vidCycle.val() / 65;
|
||||
}
|
||||
|
||||
uint currentCol()
|
||||
{
|
||||
return vidCycle.currentVal() % 65;
|
||||
return vidCycle.val() % 65;
|
||||
}
|
||||
|
||||
ubyte* getData(uint vidClock)
|
||||
@ -243,7 +254,7 @@ class Scanner_II : Scanner
|
||||
|
||||
ubyte floatingBus(ushort addr)
|
||||
{
|
||||
uint clock = vidCycle.currentVal();
|
||||
uint clock = vidCycle.val();
|
||||
if (((clock % 65) < 25) && (mode != Mode.HIRES))
|
||||
return decoder.read(
|
||||
cast(ushort)(0x1400 + (page * 0x400) + scanOffset(clock, mode)));
|
||||
@ -263,7 +274,7 @@ class Scanner_IIe : Scanner
|
||||
{
|
||||
ubyte floatingBus(ushort addr)
|
||||
{
|
||||
return displayMem[mode][page].data[scanOffset(vidCycle.currentVal(),
|
||||
return displayMem[mode][page].data[scanOffset(vidCycle.val(),
|
||||
mode)];
|
||||
// equivalent to getData()[0];
|
||||
}
|
||||
@ -280,7 +291,7 @@ class Scanner_IIe : Scanner
|
||||
|
||||
bool readVBL()
|
||||
{
|
||||
return (vidCycle.currentVal() >= (192 * 65));
|
||||
return (vidCycle.val() >= (192 * 65));
|
||||
}
|
||||
|
||||
ubyte readLowVBL()
|
||||
|
Loading…
Reference in New Issue
Block a user