/* 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.memory; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import jpcsp.Memory; import jpcsp.MemoryMap; import jpcsp.HLE.Modules; /** * A Memory implementation using a memory area allocated natively. * Using NativeMemoryUtils to perform the native operations. * * @author gid15 * */ public class NativeMemory extends Memory { private long memory; private int memorySize; @Override public boolean allocate() { NativeMemoryUtils.init(); memorySize = MemoryMap.END_RAM + 1; memory = NativeMemoryUtils.alloc(memorySize); if (memory == 0) { // Not enough native memory available return false; } log.info(String.format("Using NativeMemory(littleEndian=%b)", NativeMemoryUtils.isLittleEndian())); return super.allocate(); } @Override public void Initialise() { NativeMemoryUtils.memset(memory, 0, 0, memorySize); } @Override public int read8(int address) { address &= addressMask; return NativeMemoryUtils.read8(memory, address); } @Override public int read16(int address) { address &= addressMask; return NativeMemoryUtils.read16(memory, address); } @Override public int read32(int address) { address &= addressMask; return NativeMemoryUtils.read32(memory, address); } @Override public void write8(int address, byte data) { address &= addressMask; NativeMemoryUtils.write8(memory, address, data); Modules.sceDisplayModule.write8(address); } @Override public void write16(int address, short data) { address &= addressMask; NativeMemoryUtils.write16(memory, address, data); Modules.sceDisplayModule.write16(address); } @Override public void write32(int address, int data) { address &= addressMask; NativeMemoryUtils.write32(memory, address, data); Modules.sceDisplayModule.write32(address); } @Override public void memset(int address, byte data, int length) { address &= addressMask; NativeMemoryUtils.memset(memory, address, data, length); } @Override public Buffer getMainMemoryByteBuffer() { return null; } @Override public Buffer getBuffer(int address, int length) { address &= addressMask; ByteBuffer buffer = NativeMemoryUtils.getBuffer(memory, address, length); // Set the correct byte order if (NativeMemoryUtils.isLittleEndian()) { buffer.order(ByteOrder.LITTLE_ENDIAN); } else { buffer.order(ByteOrder.BIG_ENDIAN); } return buffer; } @Override public void copyToMemory(int address, ByteBuffer source, int length) { address &= addressMask; length = Math.min(length, source.capacity()); if (source.isDirect()) { NativeMemoryUtils.copyBufferToMemory(memory, address, source, source.position(), length); } else { for (; length > 0; address++, length--) { NativeMemoryUtils.write8(memory, address, source.get()); } } } @Override protected void memcpy(int destination, int source, int length, boolean checkOverlap) { if (length <= 0) { return; } destination &= addressMask; source &= addressMask; Modules.sceDisplayModule.write(destination); if (!checkOverlap || source >= destination || !areOverlapping(destination, source, length)) { NativeMemoryUtils.memcpy(memory, destination, memory, source, length); } else { // Source and destination are overlapping and source < destination, // copy from the tail. for (int i = length - 1; i >= 0; i--) { int b = NativeMemoryUtils.read8(memory, source + i); NativeMemoryUtils.write8(memory, destination + i, b); } } } }