2012-03-14 00:43:29 +00:00
|
|
|
/+
|
|
|
|
+ system/base.d
|
|
|
|
+
|
|
|
|
+ Copyright: 2007 Gerald Stocker
|
|
|
|
+
|
2012-03-15 06:21:12 +00:00
|
|
|
+ This file is part of twoapple-reboot.
|
2012-03-14 00:43:29 +00:00
|
|
|
+
|
2012-03-15 06:21:12 +00:00
|
|
|
+ twoapple-reboot is free software; you can redistribute it and/or modify
|
2012-03-14 00:43:29 +00:00
|
|
|
+ it under the terms of the GNU General Public License as published by
|
|
|
|
+ the Free Software Foundation; either version 2 of the License, or
|
|
|
|
+ (at your option) any later version.
|
|
|
|
+
|
2012-03-15 06:21:12 +00:00
|
|
|
+ twoapple-reboot is distributed in the hope that it will be useful,
|
2012-03-14 00:43:29 +00:00
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
+ GNU General Public License for more details.
|
|
|
|
+
|
|
|
|
+ You should have received a copy of the GNU General Public License
|
2012-03-15 06:21:12 +00:00
|
|
|
+ along with twoapple-reboot; if not, write to the Free Software
|
2012-03-14 00:43:29 +00:00
|
|
|
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
+/
|
|
|
|
|
|
|
|
module system.base;
|
|
|
|
|
|
|
|
import timer;
|
|
|
|
import memory;
|
|
|
|
import d6502.base;
|
|
|
|
|
2012-03-23 06:22:02 +00:00
|
|
|
private alias d6502.base.CpuBase!(Strict.no, Cumulative.no) CpuBase;
|
|
|
|
|
2012-03-14 00:43:29 +00:00
|
|
|
import ui.sound;
|
|
|
|
import ui.inputevents;
|
|
|
|
|
|
|
|
import system.io;
|
|
|
|
import system.video;
|
|
|
|
import iomem;
|
|
|
|
import video.base;
|
|
|
|
import system.peripheral;
|
|
|
|
|
|
|
|
class System
|
|
|
|
{
|
|
|
|
Timer timer;
|
|
|
|
Timer.Cycle deviceCycle;
|
|
|
|
AddressDecoder decoder;
|
|
|
|
SoftSwitchPage switches;
|
|
|
|
CpuBase cpu;
|
|
|
|
IOMem ioMem;
|
|
|
|
Peripherals peripherals;
|
|
|
|
|
|
|
|
class Memory
|
|
|
|
{
|
|
|
|
PrimaryMem mainRam;
|
|
|
|
Rom mainRom;
|
|
|
|
VideoPages vidPages;
|
|
|
|
|
|
|
|
this(ubyte[] romDump)
|
|
|
|
{
|
|
|
|
mainRam = new PrimaryMem(0x0000, 0xC000);
|
|
|
|
mainRam.debugName = "RAM";
|
|
|
|
mainRom = new Rom(0xD000, 0x3000,
|
2012-03-14 12:24:35 +00:00
|
|
|
romDump[($-12288)..$]);
|
2012-03-14 00:43:29 +00:00
|
|
|
mainRom.debugName = "ROM";
|
|
|
|
vidPages.lores1 = new SliceMem(0x0400, 0x0400, mainRam);
|
|
|
|
vidPages.lores2 = new SliceMem(0x0800, 0x0400, mainRam);
|
|
|
|
vidPages.hires1 = new SliceMem(0x2000, 0x2000, mainRam);
|
|
|
|
vidPages.hires2 = new SliceMem(0x4000, 0x2000, mainRam);
|
|
|
|
}
|
|
|
|
|
|
|
|
void reboot()
|
|
|
|
{
|
|
|
|
mainRam.reboot();
|
|
|
|
vidPages.reboot();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Video video_;
|
|
|
|
Memory memory_;
|
|
|
|
IO io_;
|
|
|
|
|
|
|
|
abstract IO newIO();
|
|
|
|
abstract CpuBase newCpu();
|
|
|
|
abstract Video newVideo(ubyte[] vidRom);
|
|
|
|
abstract IOMem newIOMem();
|
|
|
|
abstract Peripherals newPeripherals();
|
|
|
|
|
|
|
|
this(ubyte[] romDump)
|
|
|
|
{
|
|
|
|
initTimer();
|
|
|
|
initMemory(romDump);
|
|
|
|
initCpu();
|
|
|
|
initIO(null); // XXX where is vidRom passed in?
|
|
|
|
decoder.nullRead = &video_.scanner.floatingBus;
|
|
|
|
|
|
|
|
peripherals = newPeripherals();
|
|
|
|
peripherals.install(cpu, decoder, memory_.mainRom);
|
|
|
|
ioMem.initialize(decoder, switches, timer, peripherals);
|
|
|
|
|
|
|
|
input.onReset = &reset;
|
|
|
|
switches.setFloatingBus(&video_.scanner.floatingBus);
|
|
|
|
}
|
|
|
|
|
|
|
|
void reboot()
|
|
|
|
{
|
|
|
|
cpu.reboot();
|
|
|
|
deviceCycle.restart();
|
|
|
|
memory_.reboot();
|
|
|
|
ioMem.reboot();
|
|
|
|
io_.reboot();
|
|
|
|
peripherals.reboot();
|
|
|
|
video_.reboot();
|
|
|
|
}
|
|
|
|
|
|
|
|
void initTimer()
|
|
|
|
{
|
|
|
|
// XXX constants? variables?
|
|
|
|
timer = new Timer(10_205, 1_020_484);
|
|
|
|
deviceCycle =
|
|
|
|
timer.startCycle(timer.primaryCounter.startLength * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void initMemory(ubyte[] romDump)
|
|
|
|
{
|
|
|
|
memory_ = new Memory(romDump);
|
|
|
|
decoder = new AddressDecoder();
|
|
|
|
switches = new SoftSwitchPage();
|
|
|
|
decoder.installSwitches(switches);
|
|
|
|
decoder.install(memory_.mainRam);
|
|
|
|
decoder.install(memory_.mainRom);
|
|
|
|
ioMem = newIOMem();
|
|
|
|
}
|
|
|
|
|
|
|
|
void initCpu()
|
|
|
|
{
|
|
|
|
cpu = newCpu();
|
|
|
|
debug(disassemble) cpu.memoryName = &decoder.memoryReadName;
|
|
|
|
cpu.tick = &timer.tick;
|
|
|
|
timer.onPrimaryStop(&primaryStop);
|
|
|
|
cpu.memoryRead = &decoder.read;
|
|
|
|
cpu.memoryWrite = &decoder.write;
|
|
|
|
}
|
|
|
|
|
|
|
|
void initIO(ubyte[] vidRom)
|
|
|
|
{
|
|
|
|
io_ = newIO();
|
|
|
|
video_ = newVideo(vidRom);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool primaryStop()
|
|
|
|
{
|
|
|
|
cpu.stop();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
peripherals.reset();
|
|
|
|
cpu.resetLow();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint checkpoint()
|
|
|
|
{
|
|
|
|
return timer.primaryCounter.currentLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint sinceCheckpoint(uint cp)
|
|
|
|
{
|
|
|
|
uint currentLength = timer.primaryCounter.currentLength;
|
|
|
|
return ((currentLength == timer.primaryCounter.startLength) ?
|
|
|
|
cp : (cp - currentLength));
|
|
|
|
}
|
|
|
|
|
|
|
|
void execute()
|
|
|
|
{
|
|
|
|
cpu.run(true);
|
|
|
|
|
|
|
|
soundCard.process();
|
|
|
|
soundCard.start();
|
|
|
|
|
|
|
|
video_.signal.update();
|
|
|
|
deviceCycle.restart();
|
|
|
|
// XXX peripherals get notification
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class II : System
|
|
|
|
{
|
|
|
|
import d6502.nmosundoc : NmosUndoc;
|
|
|
|
|
|
|
|
int revision;
|
|
|
|
|
|
|
|
this(ubyte[] romDump)
|
|
|
|
{
|
|
|
|
// XXX FIXME XXX
|
|
|
|
revision = int.max;
|
|
|
|
super(romDump);
|
|
|
|
}
|
|
|
|
|
|
|
|
CpuBase newCpu()
|
|
|
|
{
|
2012-03-23 06:22:02 +00:00
|
|
|
return new NmosUndoc!(Strict.no, Cumulative.no)();
|
2012-03-14 00:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IO newIO()
|
|
|
|
{
|
|
|
|
return new IO_II(switches, timer, deviceCycle);
|
|
|
|
}
|
|
|
|
|
|
|
|
Video newVideo(ubyte[] vidRom)
|
|
|
|
{
|
|
|
|
return new Video_II(switches, memory_.vidPages, timer, vidRom,
|
|
|
|
&io_.kbd.peekLatch, decoder);
|
|
|
|
}
|
|
|
|
|
|
|
|
IOMem newIOMem()
|
|
|
|
{
|
|
|
|
return new IOMem();
|
|
|
|
}
|
|
|
|
|
|
|
|
Peripherals newPeripherals()
|
|
|
|
{
|
|
|
|
return new Peripherals_II();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
import ioummu;
|
|
|
|
|
|
|
|
class IIe : System
|
|
|
|
{
|
|
|
|
import d6502.cmos : Cmos;
|
|
|
|
|
|
|
|
AuxiliaryCard auxCard;
|
|
|
|
MMU mmu;
|
|
|
|
IOU iou;
|
|
|
|
|
|
|
|
this(ubyte[] romDump)
|
|
|
|
{
|
|
|
|
// XXX if different or no aux card?
|
|
|
|
//auxMemory = new Memory();
|
|
|
|
super(romDump);
|
|
|
|
}
|
|
|
|
|
|
|
|
void reboot()
|
|
|
|
{
|
|
|
|
super.reboot();
|
|
|
|
auxCard.reboot();
|
|
|
|
mmu.reboot();
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
auxCard.reset();
|
|
|
|
mmu.reset();
|
|
|
|
super.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
CpuBase newCpu()
|
|
|
|
{
|
|
|
|
// XXX this is enhanced
|
2012-03-23 06:22:02 +00:00
|
|
|
return new Cmos!(Strict.no, Cumulative.no)();
|
2012-03-14 00:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IO newIO()
|
|
|
|
{
|
|
|
|
return new IO_IIe(switches, timer, deviceCycle);
|
|
|
|
}
|
|
|
|
|
|
|
|
Video newVideo(ubyte[] vidRom)
|
|
|
|
{
|
|
|
|
return new Video_IIe(switches, memory_.vidPages, timer, vidRom,
|
|
|
|
&io_.kbd.peekLatch, auxCard.vidPages);
|
|
|
|
}
|
|
|
|
|
|
|
|
IOMem newIOMem()
|
|
|
|
{
|
|
|
|
return mmu.ioMem;
|
|
|
|
}
|
|
|
|
|
|
|
|
Peripherals newPeripherals()
|
|
|
|
{
|
|
|
|
return new Peripherals_IIe();
|
|
|
|
}
|
|
|
|
|
|
|
|
void initMemory(ubyte[] romDump)
|
|
|
|
{
|
|
|
|
mmu = new MMU();
|
|
|
|
mmu.ioMem = new IOMem_IIe();
|
|
|
|
mmu.ioMem.setRom(romDump);
|
|
|
|
|
|
|
|
super.initMemory(romDump);
|
|
|
|
|
|
|
|
// XXX XXX XXX
|
|
|
|
// allow for different card from config
|
|
|
|
auxCard = new Extended80ColumnCard();
|
|
|
|
|
|
|
|
mmu.init(switches, auxCard, decoder, memory_.mainRam,
|
|
|
|
memory_.mainRom);
|
|
|
|
}
|
|
|
|
|
|
|
|
void initIO(ubyte[] vidRom)
|
|
|
|
{
|
|
|
|
super.initIO(vidRom);
|
|
|
|
iou = new IOU(io_, video_.signal);
|
|
|
|
iou.initSwitches(switches);
|
|
|
|
mmu.initIO(video_.scanner, &io_.kbd.peekLatch);
|
|
|
|
}
|
|
|
|
}
|