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 } } }