twoapple-reboot/src/system/base.d

231 lines
5.7 KiB
D

/+
+ system/base.d
+
+ Copyright: 2007 Gerald Stocker
+
+ This file is part of twoapple-reboot.
+
+ twoapple-reboot is free software; you can redistribute it and/or modify
+ 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.
+
+ twoapple-reboot is distributed in the hope that it will be useful,
+ 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
+ along with twoapple-reboot; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+/
module system.base;
import timer;
import memory;
import cpu.d6502;
import ui.sound;
import ui.inputevents;
import system.io;
import system.video;
import iomem;
import video.base;
import system.peripheral;
import ioummu;
class SystemBase
{
Video video_;
Timer timer;
abstract void reboot();
abstract void reset();
abstract void execute();
}
class System(string chip) : SystemBase
{
Timer.Cycle deviceCycle;
AddressDecoder decoder;
SoftSwitchPage switches;
Cpu!(chip, AddressDecoder, Timer) cpu;
// XXX
bool* cpuRun, signalActive, resetLow;
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,
romDump[($-12288)..$]);
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();
}
}
Memory memory_;
IO io_;
static if (chip == "65C02")
{
AuxiliaryCard auxCard;
MMU mmu;
IOU iou;
}
this(ubyte[] romDump)
{
initTimer();
initMemory(romDump);
initCpu();
initIO(null); // XXX where is vidRom passed in?
decoder.nullRead = &video_.scanner.floatingBus;
static if (chip == "6502")
peripherals = new Peripherals_II();
else
peripherals = new Peripherals_IIe();
peripherals.install(decoder, memory_.mainRom);
ioMem.initialize(decoder, switches, timer, peripherals);
input.onReset = &reset;
switches.setFloatingBus(&video_.scanner.floatingBus);
}
override void reboot()
{
// XXX replace
//cpu.reboot();
deviceCycle.restart();
memory_.reboot();
ioMem.reboot();
io_.reboot();
peripherals.reboot();
video_.reboot();
static if (chip == "65C02")
{
auxCard.reboot();
mmu.reboot();
}
}
void initTimer()
{
// XXX constants? variables?
timer = new Timer(10_205, 1_020_484, &primaryStop);
deviceCycle =
timer.new Cycle(timer.primaryLength * 2);
}
void initMemory(ubyte[] romDump)
{
static if (chip == "65C02")
{
mmu = new MMU();
mmu.ioMem = new IOMem_IIe();
mmu.ioMem.setRom(romDump);
}
memory_ = new Memory(romDump);
decoder = new AddressDecoder();
switches = new SoftSwitchPage();
decoder.installSwitches(switches);
decoder.install(memory_.mainRam);
decoder.install(memory_.mainRom);
static if (chip == "6502")
ioMem = new IOMem();
else
{
ioMem = mmu.ioMem;
auxCard = new Extended80ColumnCard();
mmu.init(switches, auxCard, decoder, memory_.mainRam,
memory_.mainRom);
}
}
void initCpu()
{
cpu = new Cpu!(chip, AddressDecoder, Timer)(decoder, timer);
// XXX
cpuRun = &cpu.keepRunning;
signalActive = &cpu.signalActive;
resetLow = &cpu.resetLow;
debug(disassemble) cpu.memoryName = &decoder.memoryReadName;
// timer.onPrimaryStop(&primaryStop);
}
void initIO(ubyte[] vidRom)
{
static if (chip == "6502")
{
io_ = new IO_II(switches, timer, deviceCycle);
video_ = new Video_II(switches, memory_.vidPages, timer, vidRom,
&io_.kbd.peekLatch, decoder);
}
else
{
io_ = new IO_IIe(switches, timer, deviceCycle);
video_ = new Video_IIe(switches, memory_.vidPages, timer, vidRom,
&io_.kbd.peekLatch, auxCard.vidPages);
iou = new IOU(io_, video_.signal);
iou.initSwitches(switches);
mmu.initIO(video_.scanner, &io_.kbd.peekLatch);
}
}
bool primaryStop()
{
*cpuRun = false;
return true;
}
override void reset()
{
static if (chip == "65C02")
{
auxCard.reset();
mmu.reset();
}
peripherals.reset();
*signalActive = true;
*resetLow = true;
}
override void execute()
{
cpu.run(true);
soundCard.process();
soundCard.start();
video_.signal.update();
deviceCycle.restart();
// XXX peripherals get notification
}
}