/*
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.HLE;
import jpcsp.Memory;
import jpcsp.memory.IMemoryReader;
import jpcsp.memory.IMemoryWriter;
import jpcsp.memory.MemoryReader;
import jpcsp.memory.MemoryWriter;
import jpcsp.util.Utilities;
final public class TPointer implements ITPointerBase {
private Memory memory;
private int address;
public static final TPointer NULL = new TPointer((Memory) null, 0);
public TPointer(Memory memory, int address) {
this.memory = memory;
this.address = address & Memory.addressMask;
}
public TPointer(TPointer base) {
memory = base.getMemory();
address = base.getAddress();
}
public TPointer(TPointer base, int addressOffset) {
memory = base.getMemory();
if (base.isNull()) {
address = 0;
} else {
address = base.getAddress() + addressOffset;
}
}
public void add(int addressOffset) {
if (isNotNull()) {
address += addressOffset;
}
}
@Override
public boolean isAddressGood() {
return Memory.isAddressGood(address);
}
@Override
public boolean isAlignedTo(int offset) {
return (address % offset) == 0;
}
@Override
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address & Memory.addressMask;
}
public Memory getMemory() {
return memory;
}
@Override
public boolean isNull() {
return address == 0;
}
@Override
public boolean isNotNull() {
return address != 0;
}
public byte getValue8() { return getValue8(0); }
public short getValue16() { return getValue16(0); }
public int getValue32() { return getValue32(0); }
public long getValue64() { return getValue64(0); }
public void setValue8(byte value) { setValue8(0, value); }
public void setValue16(short value) { setValue16(0, value); }
public void setValue32(int value) { setValue32(0, value); }
public void setValue32(boolean value) { setValue32(0, value); }
public void setValue64(long value) { setValue64(0, value); }
public byte getValue8(int offset) { return (byte) memory.read8(address + offset); }
public short getValue16(int offset) { return (short) memory.read16(address + offset); }
public int getValue32(int offset) { return memory.read32(address + offset); }
public long getValue64(int offset) { return memory.read64(address + offset); }
public void setValue8(int offset, byte value) { if (isNotNull()) memory.write8(address + offset, value); }
public void setValue16(int offset, short value) { if (isNotNull()) memory.write16(address + offset, value); }
public void setValue32(int offset, int value) { if (isNotNull()) memory.write32(address + offset, value); }
public void setValue32(int offset, boolean value) { if (isNotNull()) memory.write32(address + offset, value ? 1 : 0); }
public void setValue64(int offset, long value) { if (isNotNull()) memory.write64(address + offset, value); }
public float getFloat() {
return getFloat(0);
}
public float getFloat(int offset) {
return Float.intBitsToFloat(getValue32(offset));
}
public void setFloat(float value) {
setFloat(0, value);
}
public void setFloat(int offset, float value) {
setValue32(offset, Float.floatToRawIntBits(value));
}
public String getStringZ() {
return Utilities.readStringZ(memory, address);
}
public String getStringNZ(int n) {
return getStringNZ(0, n);
}
public String getStringNZ(int offset, int n) {
return Utilities.readStringNZ(memory, address + offset, n);
}
public void setStringNZ(int n, String s) {
setStringNZ(0, n, s);
}
public void setStringNZ(int offset, int n, String s) {
Utilities.writeStringNZ(memory, address + offset, n, s);
}
public void setStringZ(String s) {
Utilities.writeStringZ(memory, address, s);
}
public byte[] getArray8(int n) {
return getArray8(0, n);
}
public byte[] getArray8(int offset, int n) {
byte[] bytes = new byte[n];
IMemoryReader memoryReader = MemoryReader.getMemoryReader(getAddress() + offset, n, 1);
for (int i = 0; i < n; i++) {
bytes[i] = (byte) memoryReader.readNext();
}
return bytes;
}
public void setArray(byte[] bytes, int n) {
setArray(0, bytes, n);
}
public void setArray(int offset, byte[] bytes, int n) {
setArray(offset, bytes, 0, n);
}
public void setArray(int offset, byte[] bytes, int bytesOffset, int n) {
IMemoryWriter memoryWriter = MemoryWriter.getMemoryWriter(getAddress() + offset, n, 1);
for (int i = 0; i < n; i++) {
memoryWriter.writeNext(bytes[bytesOffset + i] & 0xFF);
}
memoryWriter.flush();
}
public void memcpy(int src, int length) {
memcpy(0, src, length);
}
public void memcpy(int offset, int src, int length) {
if (isNotNull()) {
memory.memcpy(getAddress() + offset, src, length);
}
}
/**
* Set "length" bytes to the value "data" starting at the pointer address.
* Equivalent to
* Memory.memset(getAddress(), data, length);
*
* @param data the byte to be set in memory
* @param length the number of bytes to be set
*/
public void memset(byte data, int length) {
memset(0, data, length);
}
/**
* Set "length" bytes to the value "data" starting at the pointer address
* with the given "offset".
* Equivalent to
* Memory.memset(getAddress() + offset, data, length);
*
* @param offset the address offset from the pointer address
* @param data the byte to be set in memory
* @param length the number of bytes to be set
*/
public void memset(int offset, byte data, int length) {
if (isNotNull()) {
memory.memset(getAddress() + offset, data, length);
}
}
/**
* Set "length" bytes to the value 0 starting at the pointer address.
* Equivalent to
* Memory.memset(getAddress(), 0, length);
*
* @param length the number of bytes to be set
*/
public void clear(int length) {
clear(0, length);
}
/**
* Set "length" bytes to the value 0 starting at the pointer address
* with the given "offset".
* Equivalent to
* Memory.memset(getAddress() + offset, 0, length);
*
* @param offset the address offset from the pointer address
* @param length the number of bytes to be set
*/
public void clear(int offset, int length) {
memset(offset, (byte) 0, length);
}
public void setUnalignedValue32(int offset, int value) {
if (isNotNull()) {
Utilities.writeUnaligned32(getMemory(), getAddress() + offset, value);
}
}
@Override
public String toString() {
return String.format("0x%08X", getAddress());
}
}