231 lines
5.7 KiB
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
|
|
}
|
|
}
|