/*
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 java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import jpcsp.Memory;
import jpcsp.graphics.VideoEngine;
import jpcsp.memory.IMemoryReader;
import jpcsp.memory.MemoryReader;
/** captures a piece of RAM */
public class CaptureRAM {
private int packetSize;
private int address;
private int length;
private Buffer buffer;
public CaptureRAM(int address, int length) throws IOException {
packetSize = 8 + length;
this.address = address;
this.length = length;
Memory mem = Memory.getInstance();
if (Memory.isAddressGood(address)) {
buffer = mem.getBuffer(address, length);
}
if (buffer == null) {
throw new IOException(String.format("CaptureRAM: Unable to read buffer %08x - %08x", address, address + length));
}
}
public void write(OutputStream out) throws IOException {
DataOutputStream data = new DataOutputStream(out);
data.writeInt(packetSize);
data.writeInt(address);
data.writeInt(length);
if (buffer instanceof ByteBuffer) {
WritableByteChannel channel = Channels.newChannel(out);
channel.write((ByteBuffer)buffer);
} else {
IMemoryReader reader = MemoryReader.getMemoryReader(address, length, 1);
for (int i = 0; i < length; i++){
data.writeByte(reader.readNext());
}
}
VideoEngine.log.info(String.format("Saved memory %08x - %08x (len %08x)", address, address + length, length));
//VideoEngine.log.info("CaptureRAM write " + ((3 * 4) + length));
//data.flush();
//out.flush();
}
private CaptureRAM() {
}
public static CaptureRAM read(InputStream in) throws IOException {
CaptureRAM ramFragment = new CaptureRAM();
DataInputStream data = new DataInputStream(in);
int sizeRemaining = data.readInt();
if (sizeRemaining >= 8) {
ramFragment.address = data.readInt(); sizeRemaining -= 4;
ramFragment.length = data.readInt(); sizeRemaining -= 4;
if (sizeRemaining > data.available()) {
VideoEngine.log.warn("CaptureRAM read want=" + sizeRemaining + " available=" + data.available());
}
if (sizeRemaining >= ramFragment.length) {
ByteBuffer bb = ByteBuffer.allocate(ramFragment.length);
byte[] b = bb.array();
if (b == null) {
throw new IOException("Buffer is not backed by an array");
}
data.readFully(b, 0, ramFragment.length);
ramFragment.buffer = bb;
sizeRemaining -= ramFragment.length;
data.skipBytes(sizeRemaining);
VideoEngine.log.info(String.format("Loaded memory %08x - %08x (len %08x)",
ramFragment.address, ramFragment.address + ramFragment.length, ramFragment.length));
} else {
throw new IOException("Not enough bytes remaining in stream");
}
} else {
throw new IOException("Not enough bytes remaining in stream");
}
return ramFragment;
}
public void commit() {
Memory.getInstance().copyToMemory(address, (ByteBuffer)buffer, length);
}
public int getAddress() {
return address;
}
public int getLength() {
return length;
}
public Buffer getBuffer() {
return buffer;
}
}