pvbemu/src/desktop/vue/VIP.java

310 lines
9.5 KiB
Java

package vue;
// Java imports
import java.util.*;
// VIP state
class VIP {
// Instance fields
byte[] vram; // Video memory
// Private fields
private JavaVue vue; // Emulation state
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
VIP(JavaVue vue) {
vram = new byte[0x40000];
this.vue = vue;
}
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Process the simulation
void emulate(int cycles) {
}
// Read a value from the CPU bus
int read(int address, int type) {
address &= 0x0007FFFF;
// VRAM
if (address < 0x00040000)
return JavaVue.readBuffer(vram, address, type);
// Mirrors of character memory
if (address >= 0x00078000)
return JavaVue.readBuffer(vram,
address - 0x00078000 >> 13 << 15 | 0x00006000 |
address & 0x00001FFF,
type);
// I/O register or unmapped
int value = readRegister(address);
if (type < 2 && (address & 1) == 1)
value >>= 8;
switch (type) {
case Vue.S8 : return value << 24 >> 24;
case Vue.U8 : return value & 0x000000FF;
case Vue.S16: return value << 16 >> 16;
case Vue.S32: return value | readRegister(address + 2) << 16;
}
return value; // U16
}
// Read bytes from the CPU bus
void readBytes(int address, byte[] dest, int offset, int length) {
address &= 0x0007FFFF;
// Perform the operation
while (length > 0) {
int count;
// VRAM
if (address < 0x00040000) {
count = Math.min(length, 0x00040000 - address);
JavaVue.readBytes(vram, address, dest, offset, count);
}
// Mirrors of character memory
else if (address >= 0x00078000) {
count = Math.min(length, 0x2000 - (address & 0x1FFF));
JavaVue.readBytes(vram,
address - 0x00078000 >> 13 << 15 | 0x00006000 |
address & 0x00001FFF,
dest, offset, count);
}
// I/O register or unmapped
else {
count = Math.min(length, 0x00078000 - address);
// Read all registers in the range
while (count > 0) {
int value = readRegister(address);
// Odd address
if ((address & 1) == 1) {
dest[offset] = (byte) (value >> 8);
address++;
count --;
length --;
offset ++;
continue;
}
// Even address
int size = count == 1 ? 1 : 2;
dest[offset] = (byte) value;
if (size == 2)
dest[offset + 1] = (byte) (value >> 8);
address += size;
count -= size;
length -= size;
offset += size;
}
continue;
}
// Advance to the next region
address += count;
length -= count;
offset += count;
}
}
// System reset
void reset() {
}
// Determine the number of CPU cycles until a breakpoint could trigger
int until(int cycles) {
return cycles;
}
// Write a value to the CPU bus
void write(int address, int type, int value) {
address &= 0x0007FFFF;
// VRAM
if (address < 0x00040000) {
JavaVue.writeBuffer(vram, address, type, value);
return;
}
// Mirrors of character memory
if (address >= 0x00078000) {
JavaVue.writeBuffer(vram,
address - 0x00078000 >> 13 << 15 | 0x00006000 |
address & 0x00001FFF,
type, value);
return;
}
// I/O register or unmapped
if (type < 2 && (address & 1) == 1)
value <<= 8;
writeRegister(address, value);
if (type == Vue.S32)
writeRegister(address + 2, value >> 16);
}
// Write bytes to the CPU bus
void writeBytes(int address, byte[] src, int offset, int length) {
address &= 0x0007FFFF;
// Perform the operation
while (length > 0) {
int count;
// VRAM
if (address < 0x00040000) {
count = Math.min(length, 0x00040000 - address);
JavaVue.writeBytes(vram, address, src, offset, count);
}
// Mirrors of character memory
else if (address >= 0x00078000) {
count = Math.min(length, 0x2000 - (address & 0x1FFF));
JavaVue.writeBytes(vram,
address - 0x00078000 >> 13 << 15 | 0x00006000 |
address & 0x00001FFF,
src, offset, count);
}
// I/O register or unmapped
else {
count = Math.min(length, 0x00078000 - address);
// Write all registers in the range
while (count > 0) {
int value = src[offset] & 0xFF;
// Odd address
if ((address & 1) == 1) {
writeRegister(address, value << 8);
address++;
count --;
length --;
offset ++;
continue;
}
// Even address
int size = count == 1 ? 1 : 2;
if (size == 2)
value |= src[offset + 1] << 8;
writeRegister(address, value);
address += size;
count -= size;
length -= size;
offset += size;
}
continue;
}
// Advance to the next region
address += count;
length -= count;
offset += count;
}
}
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Read an I/O register
private int readRegister(int address) {
// Process by register
switch (address & ~1) {
case 0x0005F800: break; // INTPND
case 0x0005F802: break; // INTENB
case 0x0005F804: break; // INTCLR
case 0x0005F820: break; // DPSTTS
case 0x0005F822: break; // DPCTRL
case 0x0005F824: break; // BRTA
case 0x0005F826: break; // BRTB
case 0x0005F828: break; // BRTC
case 0x0005F82A: break; // REST
case 0x0005F82E: break; // FRMCYC
case 0x0005F830: break; // CTA
case 0x0005F840: break; // XPSTTS
case 0x0005F842: break; // XPCTRL
case 0x0005F844: break; // VER
case 0x0005F848: break; // SPT0
case 0x0005F84A: break; // SPT1
case 0x0005F84C: break; // SPT2
case 0x0005F84E: break; // SPT3
case 0x0005F860: break; // GPLT0
case 0x0005F862: break; // GPLT1
case 0x0005F864: break; // GPLT2
case 0x0005F866: break; // GPLT3
case 0x0005F868: break; // JPLT0
case 0x0005F86A: break; // JPLT1
case 0x0005F86C: break; // JPLT2
case 0x0005F86E: break; // JPLT3
case 0x0005F870: break; // BKCOL
}
// Unmapped
return 0;
}
// Write an I/O register
private void writeRegister(int address, int value) {
// Process by register
switch (address & ~1) {
case 0x0005F800: break; // INTPND
case 0x0005F802: break; // INTENB
case 0x0005F804: break; // INTCLR
case 0x0005F820: break; // DPSTTS
case 0x0005F822: break; // DPCTRL
case 0x0005F824: break; // BRTA
case 0x0005F826: break; // BRTB
case 0x0005F828: break; // BRTC
case 0x0005F82A: break; // REST
case 0x0005F82E: break; // FRMCYC
case 0x0005F830: break; // CTA
case 0x0005F840: break; // XPSTTS
case 0x0005F842: break; // XPCTRL
case 0x0005F844: break; // VER
case 0x0005F848: break; // SPT0
case 0x0005F84A: break; // SPT1
case 0x0005F84C: break; // SPT2
case 0x0005F84E: break; // SPT3
case 0x0005F860: break; // GPLT0
case 0x0005F862: break; // GPLT1
case 0x0005F864: break; // GPLT2
case 0x0005F866: break; // GPLT3
case 0x0005F868: break; // JPLT0
case 0x0005F86A: break; // JPLT1
case 0x0005F86C: break; // JPLT2
case 0x0005F86E: break; // JPLT3
case 0x0005F870: break; // BKCOL
}
}
}