/* This file is part of jpcsp. Jpcsp 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 3 of the License, or (at your option) any later version. Jpcsp 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 Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.graphics.capture; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import jpcsp.MemoryMap; import jpcsp.HLE.Modules; import jpcsp.HLE.modules.sceDisplay; import jpcsp.graphics.VideoEngine; import jpcsp.graphics.RE.IRenderingEngine; /** captures draw, depth and display buffers along with their settings (width, height, etc) */ public class CaptureDisplayDetails { private static final boolean captureRenderTargets = false; private static final int packetSize = (5 + 4) * 4; private int fbp; private int fbw; private int zbp; private int zbw; private int psm; private int topaddrFb; private int bufferwidthFb; private int pixelformatFb; private int sync; private CaptureRAM drawBuffer; private CaptureRAM depthBuffer; private CaptureRAM displayBuffer; public CaptureDisplayDetails() throws IOException { VideoEngine ge = VideoEngine.getInstance(); sceDisplay display = Modules.sceDisplayModule; fbp = ge.getFBP(); fbw = ge.getFBW(); zbp = ge.getZBP(); zbw = ge.getZBW(); psm = ge.getPSM(); topaddrFb = display.getTopAddrFb(); bufferwidthFb = display.getBufferWidthFb(); pixelformatFb = display.getPixelFormatFb(); sync = display.getSync(); // TODO clamp lengths to within valid RAM range int pixelFormatBytes = IRenderingEngine.sizeOfTextureType[psm]; drawBuffer = new CaptureRAM(fbp + MemoryMap.START_VRAM, fbw * 272 * pixelFormatBytes); depthBuffer = new CaptureRAM(zbp + MemoryMap.START_VRAM, zbw * 272 * 2); pixelFormatBytes = IRenderingEngine.sizeOfTextureType[pixelformatFb]; displayBuffer = new CaptureRAM(topaddrFb, bufferwidthFb * 272 * pixelFormatBytes); } public void write(OutputStream out) throws IOException { DataOutputStream data = new DataOutputStream(out); data.writeInt(packetSize); data.writeInt(fbp); data.writeInt(fbw); data.writeInt(zbp); data.writeInt(zbw); data.writeInt(psm); data.writeInt(topaddrFb); data.writeInt(bufferwidthFb); data.writeInt(pixelformatFb); data.writeInt(sync); //VideoEngine.log.info("CaptureDisplayDetails write " + (4 + packetSize)); if (captureRenderTargets) { // write draw buffer CaptureHeader header = new CaptureHeader(CaptureHeader.PACKET_TYPE_RAM); header.write(out); drawBuffer.write(out); // write depth buffer header = new CaptureHeader(CaptureHeader.PACKET_TYPE_RAM); header.write(out); depthBuffer.write(out); // write display buffer header = new CaptureHeader(CaptureHeader.PACKET_TYPE_RAM); header.write(out); displayBuffer.write(out); } } public static CaptureDisplayDetails read(InputStream in) throws IOException { CaptureDisplayDetails details = new CaptureDisplayDetails(); DataInputStream data = new DataInputStream(in); int sizeRemaining = data.readInt(); if (sizeRemaining >= packetSize) { details.fbp = data.readInt(); sizeRemaining -= 4; details.fbw = data.readInt(); sizeRemaining -= 4; details.zbp = data.readInt(); sizeRemaining -= 4; details.zbw = data.readInt(); sizeRemaining -= 4; details.psm = data.readInt(); sizeRemaining -= 4; details.topaddrFb = data.readInt(); sizeRemaining -= 4; details.bufferwidthFb = data.readInt(); sizeRemaining -= 4; details.pixelformatFb = data.readInt(); sizeRemaining -= 4; details.sync = data.readInt(); sizeRemaining -= 4; data.skipBytes(sizeRemaining); if (captureRenderTargets) { // read draw, depth and display buffers CaptureHeader header = CaptureHeader.read(in); int packetType = header.getPacketType(); if (packetType != CaptureHeader.PACKET_TYPE_RAM) { throw new IOException("Expected CaptureRAM(" + CaptureHeader.PACKET_TYPE_RAM + ") packet, found " + packetType); } details.drawBuffer = CaptureRAM.read(in); header = CaptureHeader.read(in); packetType = header.getPacketType(); if (packetType != CaptureHeader.PACKET_TYPE_RAM) { throw new IOException("Expected CaptureRAM(" + CaptureHeader.PACKET_TYPE_RAM + ") packet, found " + packetType); } details.depthBuffer = CaptureRAM.read(in); header = CaptureHeader.read(in); packetType = header.getPacketType(); if (packetType != CaptureHeader.PACKET_TYPE_RAM) { throw new IOException("Expected CaptureRAM(" + CaptureHeader.PACKET_TYPE_RAM + ") packet, found " + packetType); } details.displayBuffer = CaptureRAM.read(in); } } else { throw new IOException("Not enough bytes remaining in stream"); } return details; } public void commit() { sceDisplay display = Modules.sceDisplayModule; //VideoEngine ge = VideoEngine.getInstance(); // This is almost side effect free, but replay is going to trash the emulator state anyway display.hleDisplaySetFrameBuf(topaddrFb, bufferwidthFb, pixelformatFb, sync); display.hleDisplaySetGeBuf(fbp, fbw, psm, false, false); if (captureRenderTargets) { drawBuffer.commit(); depthBuffer.commit(); displayBuffer.commit(); } } }