/*
F99bMemoryModel.java
(c) 2010-2015 Edward Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.machine.f99b.memory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import org.apache.log4j.Logger;
import ejs.base.properties.IProperty;
import ejs.base.utils.FileUtils;
import v9t9.common.client.ISettingsHandler;
import v9t9.common.events.IEventNotifier;
import v9t9.common.events.NotifyEvent.Level;
import v9t9.common.files.DataFiles;
import v9t9.common.machine.IBaseMachine;
import v9t9.common.machine.IMachine;
import v9t9.common.memory.IMemoryDomain;
import v9t9.common.memory.IMemoryEntry;
import v9t9.common.memory.MemoryEntryInfo;
import v9t9.engine.memory.GplMmio;
import v9t9.engine.memory.MemoryEntry;
import v9t9.engine.memory.MemoryEntryInfoBuilder;
import v9t9.machine.EmulatorMachinesData;
import v9t9.machine.ti99.memory.BaseTI994AMemoryModel;
import v9t9.machine.ti99.memory.EnhancedRamByteArea;
/**
* F99b console memory model.
* @author ejs
*/
public class F99bMemoryModel extends BaseTI994AMemoryModel {
private static final Logger log = Logger.getLogger(F99bMemoryModel.class);
private MemoryEntry consoleEntry;
private IMemoryEntry gromEntry;
private IMemoryEntry gramDictEntry;
private IMemoryEntry gramMemoryEntry;
private IMemoryEntry cpuRomEntry;
public F99bMemoryModel(IMachine machine) {
super(machine);
}
@Override
protected void initSettings(ISettingsHandler settings) {
IProperty shipPath = settings.get(DataFiles.settingShippingRomsPath);
URL dataURL;
dataURL = EmulatorMachinesData.getDataURL("../../../build/forth99");
DataFiles.addSearchPath(settings, dataURL.toString());
shipPath.getList().add(dataURL.toString());
dataURL = EmulatorMachinesData.getDataURL("f99b/");
shipPath.getList().add(dataURL.toString());
}
protected void defineConsoleMemory(IBaseMachine machine) {
consoleEntry = new MemoryEntry("64K RAM", CPU,
0x0400, 0xFC00, new EnhancedRamByteArea(0, 0xFC00));
memory.addAndMap(consoleEntry);
}
protected void defineMmioMemory(IBaseMachine machine) {
this.memory.addAndMap(new MemoryEntry("MMIO", CPU, 0x0000, 0x0400,
new F99bConsoleMmioArea((IMachine) machine)));
}
private static MemoryEntryInfo f99bRomMemoryEntryInfo = MemoryEntryInfoBuilder
.byteMemoryEntry()
.withFilename("f99brom.bin")
.withOffset(0x400)
.withAddress(0x400)
.withSize(-(0x10000 - 0x400))
.create("Forth99 CPU ROM");
private static String FORTH_GROM = "f99bgrom.bin";
private static MemoryEntryInfo f99bGromMemoryEntryInfo = MemoryEntryInfoBuilder
.standardConsoleGrom(FORTH_GROM)
.withSize(-0x4000)
.create("Forth99 CPU GROM");
private static MemoryEntryInfo f99bGramMemoryEntryInfo = MemoryEntryInfoBuilder
.byteMemoryEntry()
.withDomain(IMemoryDomain.NAME_GRAPHICS)
.withAddress(0x4000)
.withSize(0x4000)
.storable(true)
.create("Forth99 16K GRAM Dictionary");
private static MemoryEntryInfo f99bDiskGramMemoryEntryInfo = MemoryEntryInfoBuilder
.byteMemoryEntry()
.withFilename("f99bgram.bin")
.withDomain(IMemoryDomain.NAME_GRAPHICS)
.withAddress(0x8000)
.withSize(0x8000)
.storable(true)
.create("Forth99 GRAM");
/* (non-Javadoc)
* @see v9t9.emulator.hardware.memory.StandardConsoleMemoryModel#loadMemory()
*/
@Override
public void loadMemory(IEventNotifier eventNotifier) {
try {
cpuRomEntry = memory.getMemoryEntryFactory().newMemoryEntry(
f99bRomMemoryEntryInfo);
cpuRomEntry.load();
cpuRomEntry.copySymbols(CPU);
// shrink RAM accordingly
int st = cpuRomEntry.getAddr() + 0x400 * ((cpuRomEntry.getSize() + 0x3ff) / 0x400);
int sz = 0x10000 - st;
memory.removeAndUnmap(cpuRomEntry);
memory.removeAndUnmap(consoleEntry);
consoleEntry = new MemoryEntry("64K RAM", CPU,
st, sz, new EnhancedRamByteArea(0, sz));
memory.addAndMap(consoleEntry);
memory.addAndMap(cpuRomEntry);
} catch (IOException e) {
reportLoadError(eventNotifier, f99bRomMemoryEntryInfo.getFilename(), e);
}
// GROM consists of ROM up to 16k
try {
memory.removeAndUnmap(gromEntry);
gromEntry = memory.getMemoryEntryFactory().newMemoryEntry(
f99bGromMemoryEntryInfo);
memory.addAndMap(gromEntry);
} catch (IOException e) {
reportLoadError(eventNotifier, FORTH_GROM, e);
}
// then 16k of GRAM for new dictionary
try {
memory.removeAndUnmap(gramDictEntry);
gramDictEntry = memory.getMemoryEntryFactory().newMemoryEntry(
f99bGramMemoryEntryInfo);
gramDictEntry.getArea().setLatency(0);
memory.addAndMap(gramDictEntry);
} catch (IOException e1) {
// should not happen
reportLoadError(eventNotifier, f99bGramMemoryEntryInfo.getFilename(), e1);
}
// then 32k of GRAM storage
IProperty shipPath = settings.get(DataFiles.settingShippingRomsPath);
URI shippingDiskImage = URI.create(shipPath.getList().get(0) + f99bDiskGramMemoryEntryInfo.getFilename());
URI userDiskImage = machine.getRomPathFileLocator().getWriteURI(f99bDiskGramMemoryEntryInfo.getFilename());
File userDiskImageFile = new File(userDiskImage);
if (shippingDiskImage != null && userDiskImage == null || !userDiskImageFile.exists()) {
userDiskImageFile.getParentFile().mkdirs();
InputStream is = null;
OutputStream os = null;
try {
is = machine.getRomPathFileLocator().createInputStream(shippingDiskImage);
os = machine.getRomPathFileLocator().createOutputStream(userDiskImage);
byte[] content = FileUtils.readInputStreamContentsAndClose(is);
FileUtils.writeOutputStreamContentsAndClose(os, content, content.length);
} catch (IOException e) {
log.error("Failed to copy initial disk image from " + shippingDiskImage + " to " + userDiskImage, e);
eventNotifier.notifyEvent(this, Level.ERROR,
"Failed to copy initial disk image from " + shippingDiskImage + " to " + userDiskImage);
} finally {
try { if (is != null) is.close(); } catch (IOException e) { }
try { if (os != null) os.close(); } catch (IOException e) { }
}
}
try {
memory.removeAndUnmap(gramMemoryEntry);
gramMemoryEntry = memory.getMemoryEntryFactory().newMemoryEntry(
f99bDiskGramMemoryEntryInfo);
memory.addAndMap(gramMemoryEntry);
} catch (IOException e) {
reportLoadError(eventNotifier, f99bDiskGramMemoryEntryInfo.getFilename(), e);
}
}
/* (non-Javadoc)
* @see v9t9.emulator.hardware.memory.TI994AStandardConsoleMemoryModel#resetMemory()
*/
@Override
public void resetMemory() {
}
/* (non-Javadoc)
* @see v9t9.common.memory.IMemoryModel#getRequiredRomProperties()
*/
@Override
public MemoryEntryInfo[] getRequiredRomMemoryEntries() {
return new MemoryEntryInfo[] {
f99bRomMemoryEntryInfo,
f99bGromMemoryEntryInfo,
f99bDiskGramMemoryEntryInfo,
};
}
/* (non-Javadoc)
* @see v9t9.common.memory.IMemoryModel#getOptionalRomProperties()
*/
@Override
public MemoryEntryInfo[] getOptionalRomMemoryEntries() {
return new MemoryEntryInfo[0];
}
/* (non-Javadoc)
* @see v9t9.machine.ti99.memory.BaseTI994AMemoryModel#initMemory(v9t9.common.machine.IBaseMachine)
*/
@Override
public void initMemory(IBaseMachine machine) {
gplMmio = new GplMmio(machine, GRAPHICS);
super.initMemory(machine);
}
}