mirror of https://github.com/badvision/jace.git
146 lines
4.6 KiB
Java
146 lines
4.6 KiB
Java
/*
|
|
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
package jace.core;
|
|
|
|
import jace.state.StateManager;
|
|
import jace.state.Stateful;
|
|
import java.util.Arrays;
|
|
|
|
/**
|
|
* This represents bank-switchable ram which can reside at fixed portions of the
|
|
* computer's memory. This makes it possible to switch out memory pages in a
|
|
* very efficient manner so that the MMU abstraction doesn't bury the rest of
|
|
* the emulator in messy conditionals.
|
|
*
|
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
|
*/
|
|
@Stateful
|
|
public class PagedMemory {
|
|
|
|
public enum Type {
|
|
|
|
cardFirmware(0x0c800),
|
|
languageCard(0x0d000),
|
|
firmwareMain(0x0d000),
|
|
firmware80column(0x0c300),
|
|
slotRom(0x0c100),
|
|
ram(0x0000);
|
|
protected int baseAddress;
|
|
|
|
private Type(int newBase) {
|
|
baseAddress = newBase;
|
|
}
|
|
|
|
public int getBaseAddress() {
|
|
return baseAddress;
|
|
}
|
|
}
|
|
// This is a fixed array, used for internal-only!!
|
|
@Stateful
|
|
public byte[][] internalMemory = new byte[0][];
|
|
@Stateful
|
|
public Type type;
|
|
|
|
/**
|
|
* Creates a new instance of PagedMemory
|
|
*/
|
|
public PagedMemory(int size, Type memType) {
|
|
type = memType;
|
|
internalMemory = new byte[size >> 8][256];
|
|
for (int i = 0; i < size; i += 256) {
|
|
byte[] b = new byte[256];
|
|
Arrays.fill(b, (byte) 0x00);
|
|
internalMemory[i >> 8] = b;
|
|
}
|
|
}
|
|
|
|
public PagedMemory(byte[] romData, Type memType) {
|
|
type = memType;
|
|
loadData(romData);
|
|
}
|
|
|
|
public void loadData(byte[] romData) {
|
|
for (int i = 0; i < romData.length; i += 256) {
|
|
byte[] b = new byte[256];
|
|
for (int j = 0; j < 256; j++) {
|
|
b[j] = romData[i + j];
|
|
}
|
|
internalMemory[i >> 8] = b;
|
|
}
|
|
}
|
|
|
|
public void loadData(byte[] romData, int offset, int length) {
|
|
for (int i = 0; i < length; i += 256) {
|
|
byte[] b = new byte[256];
|
|
for (int j = 0; j < 256; j++) {
|
|
b[j] = romData[offset + i + j];
|
|
}
|
|
internalMemory[i >> 8] = b;
|
|
}
|
|
}
|
|
|
|
public byte[][] getMemory() {
|
|
return internalMemory;
|
|
}
|
|
|
|
public byte[] get(int pageNumber) {
|
|
return internalMemory[pageNumber];
|
|
}
|
|
|
|
public void set(int pageNumber, byte[] bank) {
|
|
internalMemory[pageNumber] = bank;
|
|
}
|
|
|
|
public byte[] getMemoryPage(int memoryBase) {
|
|
int offset = memoryBase - type.baseAddress;
|
|
// int page = offset >> 8;
|
|
int page = (offset >> 8) & 0x0ff;
|
|
// return get(page);
|
|
return internalMemory[page];
|
|
}
|
|
|
|
public void setBanks(int sourceStart, int sourceLength, int targetStart, PagedMemory source) {
|
|
for (int i = 0; i < sourceLength; i++) {
|
|
set(targetStart + i, source.get(sourceStart + i));
|
|
}
|
|
}
|
|
|
|
public byte readByte(int address) {
|
|
return getMemoryPage(address)[address & 0x0ff];
|
|
}
|
|
|
|
public void writeByte(int address, byte value) {
|
|
byte[] page = getMemoryPage(address);
|
|
StateManager.markDirtyValue(page);
|
|
getMemoryPage(address)[address & 0x0ff] = value;
|
|
}
|
|
|
|
public void fillBanks(PagedMemory source) {
|
|
byte[][] sourceMemory = source.getMemory();
|
|
int sourceBase = source.type.getBaseAddress() >> 8;
|
|
int thisBase = type.getBaseAddress() >> 8;
|
|
int start = sourceBase > thisBase ? sourceBase : thisBase;
|
|
int sourceEnd = sourceBase + source.getMemory().length;
|
|
int thisEnd = thisBase + getMemory().length;
|
|
int end = sourceEnd < thisEnd ? sourceEnd : thisEnd;
|
|
for (int i = start; i < end; i++) {
|
|
set(i - thisBase, sourceMemory[i - sourceBase]);
|
|
}
|
|
}
|
|
} |