2026-03-01 12:16:08 +08:00
# include "stdafx.h"
# include "IntBuffer.h"
# include "FloatBuffer.h"
# include "ByteBuffer.h"
ByteBuffer : : ByteBuffer ( unsigned int capacity ) : Buffer ( capacity )
{
hasBackingArray = false ;
buffer = new byte [ capacity ] ;
memset ( buffer , 0 , sizeof ( byte ) * capacity ) ;
byteOrder = BIGENDIAN ;
}
//Allocates a new direct byte buffer.
//The new buffer's position will be zero, its limit will be its capacity, and its mark will be undefined. Whether or not it has a backing array is unspecified.
//
//Parameters:
//capacity - The new buffer's capacity, in bytes
//Returns:
//The new byte buffer
ByteBuffer * ByteBuffer : : allocateDirect ( int capacity )
{
return new ByteBuffer ( capacity ) ;
}
ByteBuffer : : ByteBuffer ( unsigned int capacity , byte * backingArray ) : Buffer ( capacity )
{
hasBackingArray = true ;
buffer = backingArray ;
}
ByteBuffer : : ~ ByteBuffer ( )
{
if ( ! hasBackingArray )
delete [ ] buffer ;
}
//Wraps a byte array into a buffer.
//The new buffer will be backed by the given byte array; that is, modifications to the buffer will cause the array
//to be modified and vice versa. The new buffer's capacity and limit will be array.length, its position will be zero,
//and its mark will be undefined. Its backing array will be the given array, and its array offset will be zero.
//
//Parameters:
//array - The array that will back this buffer
//Returns:
//The new byte buffer
ByteBuffer * ByteBuffer : : wrap ( byteArray & b )
{
return new ByteBuffer ( b . length , b . data ) ;
}
//Allocates a new byte buffer.
//The new buffer's position will be zero, its limit will be its capacity, and its mark will be undefined.
//It will have a backing array, and its array offset will be zero.
//
//Parameters:
//capacity - The new buffer's capacity, in bytes
//Returns:
//The new byte buffer
ByteBuffer * ByteBuffer : : allocate ( unsigned int capacity )
{
return new ByteBuffer ( capacity ) ;
}
//Modifies this buffer's byte order.
//Parameters:
//bo - The new byte order, either BIGENDIAN or LITTLEENDIAN
void ByteBuffer : : order ( ByteOrder bo )
{
byteOrder = bo ;
}
//Flips this buffer. The limit is set to the current position and then the position is set to zero.
//If the mark is defined then it is discarded.
//
//Returns:
//This buffer
ByteBuffer * ByteBuffer : : flip ( )
{
m_limit = m_position ;
m_position = 0 ;
return this ;
}
// 4J Added so we can write this to a file
byte * ByteBuffer : : getBuffer ( )
{
return buffer ;
}
int ByteBuffer : : getSize ( )
{
// TODO 4J Stu - Should this be the capcity and not the limit?
return m_limit ;
}
// End 4J
//Absolute get method. Reads the byte at the given index.
//Parameters:
//index - The index from which the byte will be read
//Returns:
//The byte at the given index
//Throws:
//IndexOutOfBoundsException - If index is negative or not smaller than the buffer's limit
BYTE ByteBuffer : : get ( int index )
{
assert ( index < m_limit ) ;
assert ( index > = 0 ) ;
return buffer [ index ] ;
}
//Relative get method for reading an int value.
//Reads the next four bytes at this buffer's current position, composing them into an int value according to the
//current byte order, and then increments the position by four.
//
//Returns:
//The int value at the buffer's current position
int ByteBuffer : : getInt ( )
{
assert ( m_position + 3 < m_limit ) ;
int value = 0 ;
int b1 = buffer [ m_position ] ;
int b2 = buffer [ m_position + 1 ] ;
int b3 = buffer [ m_position + 2 ] ;
int b4 = buffer [ m_position + 3 ] ;
m_position + = 4 ;
if ( byteOrder = = BIGENDIAN )
{
value = ( b1 < < 24 ) | ( b2 < < 16 ) | ( b3 < < 8 ) | b4 ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
value = b1 | ( b2 < < 8 ) | ( b3 < < 16 ) | ( b4 < < 24 ) ;
}
return value ;
}
//Absolute get method for reading an int value.
//Reads four bytes at the given index, composing them into a int value according to the current byte order.
//
//Parameters:
//index - The index from which the bytes will be read
//Returns:
//The int value at the given index
int ByteBuffer : : getInt ( unsigned int index )
{
assert ( index + 3 < m_limit ) ;
int value = 0 ;
int b1 = buffer [ index ] ;
int b2 = buffer [ index + 1 ] ;
int b3 = buffer [ index + 2 ] ;
int b4 = buffer [ index + 3 ] ;
if ( byteOrder = = BIGENDIAN )
{
value = ( b1 < < 24 ) | ( b2 < < 16 ) | ( b3 < < 8 ) | b4 ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
value = b1 | ( b2 < < 8 ) | ( b3 < < 16 ) | ( b4 < < 24 ) ;
}
return value ;
}
//Relative get method for reading a long value.
//Reads the next eight bytes at this buffer's current position, composing them into a long value according to the current byte order,
//and then increments the position by eight.
//
//Returns:
//The long value at the buffer's current position
2026-03-02 17:39:35 +07:00
__int64 ByteBuffer : : getLong ( )
2026-03-01 12:16:08 +08:00
{
assert ( m_position + 8 < m_limit ) ;
2026-03-02 17:39:35 +07:00
__int64 value = 0 ;
2026-03-01 12:16:08 +08:00
2026-03-02 17:39:35 +07:00
__int64 b1 = buffer [ m_position ] ;
__int64 b2 = buffer [ m_position + 1 ] ;
__int64 b3 = buffer [ m_position + 2 ] ;
__int64 b4 = buffer [ m_position + 3 ] ;
__int64 b5 = buffer [ m_position + 4 ] ;
__int64 b6 = buffer [ m_position + 5 ] ;
__int64 b7 = buffer [ m_position + 6 ] ;
__int64 b8 = buffer [ m_position + 7 ] ;
2026-03-01 12:16:08 +08:00
m_position + = 8 ;
if ( byteOrder = = BIGENDIAN )
{
value = ( b1 < < 56 ) | ( b2 < < 48 ) | ( b3 < < 40 ) | ( b4 < < 32 ) | ( b5 < < 24 ) | ( b6 < < 16 ) | ( b7 < < 8 ) | b8 ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
value = b1 | ( b2 < < 8 ) | ( b3 < < 16 ) | ( b4 < < 24 ) | ( b5 < < 32 ) | ( b6 < < 40 ) | ( b7 < < 48 ) | ( b8 < < 56 ) ;
}
return value ;
}
//Relative get method for reading a short value.
//Reads the next two bytes at this buffer's current position, composing them into a short value according to the current
//byte order, and then increments the position by two.
//
//Returns:
//The short value at the buffer's current position
short ByteBuffer : : getShort ( )
{
assert ( m_position + 1 < m_limit ) ;
short value = 0 ;
short b1 = buffer [ m_position ] ;
short b2 = buffer [ m_position + 1 ] ;
m_position + = 2 ;
if ( byteOrder = = BIGENDIAN )
{
value = ( b1 < < 8 ) | b2 ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
value = b1 | ( b2 < < 8 ) ;
}
return value ;
}
void ByteBuffer : : getShortArray ( shortArray & s )
{
// TODO 4J Stu - Should this function be writing from the start of the buffer, or from position?
// And should it update position?
assert ( s . length > = m_limit / 2 ) ;
// 4J Stu - Assumes big endian
memcpy ( s . data , buffer , ( m_limit - m_position ) ) ;
}
//Absolute put method (optional operation).
//Writes the given byte into this buffer at the given index.
//
//Parameters:
//index - The index at which the byte will be written
//b - The byte value to be written
//Returns:
//This buffer
//Throws:
//IndexOutOfBoundsException - If index is negative or not smaller than the buffer's limit
//ReadOnlyBufferException - If this buffer is read-only
ByteBuffer * ByteBuffer : : put ( int index , byte b )
{
assert ( index < m_limit ) ;
assert ( index > = 0 ) ;
buffer [ index ] = b ;
return this ;
}
//Relative put method for writing an int value (optional operation).
//Writes four bytes containing the given int value, in the current byte order, into this buffer at the current position,
//and then increments the position by four.
//
//Parameters:
//value - The int value to be written
//Returns:
//This buffer
ByteBuffer * ByteBuffer : : putInt ( int value )
{
assert ( m_position + 3 < m_limit ) ;
if ( byteOrder = = BIGENDIAN )
{
buffer [ m_position ] = ( value > > 24 ) & 0xFF ;
buffer [ m_position + 1 ] = ( value > > 16 ) & 0xFF ;
buffer [ m_position + 2 ] = ( value > > 8 ) & 0xFF ;
buffer [ m_position + 3 ] = value & 0xFF ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
buffer [ m_position ] = value & 0xFF ;
buffer [ m_position + 1 ] = ( value > > 8 ) & 0xFF ;
buffer [ m_position + 2 ] = ( value > > 16 ) & 0xFF ;
buffer [ m_position + 3 ] = ( value > > 24 ) & 0xFF ;
}
m_position + = 4 ;
return this ;
}
//Absolute put method for writing an int value (optional operation).
//Writes four bytes containing the given int value, in the current byte order, into this buffer at the given index.
//
//Parameters:
//index - The index at which the bytes will be written
//value - The int value to be written
//Returns:
//This buffer
ByteBuffer * ByteBuffer : : putInt ( unsigned int index , int value )
{
assert ( index + 3 < m_limit ) ;
if ( byteOrder = = BIGENDIAN )
{
buffer [ index ] = ( value > > 24 ) & 0xFF ;
buffer [ index + 1 ] = ( value > > 16 ) & 0xFF ;
buffer [ index + 2 ] = ( value > > 8 ) & 0xFF ;
buffer [ index + 3 ] = value & 0xFF ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
buffer [ index ] = value & 0xFF ;
buffer [ index + 1 ] = ( value > > 8 ) & 0xFF ;
buffer [ index + 2 ] = ( value > > 16 ) & 0xFF ;
buffer [ index + 3 ] = ( value > > 24 ) & 0xFF ;
}
return this ;
}
//Relative put method for writing a short value (optional operation).
//Writes two bytes containing the given short value, in the current byte order, into this buffer at the current position,
//and then increments the position by two.
//
//Parameters:
//value - The short value to be written
//Returns:
//This buffer
ByteBuffer * ByteBuffer : : putShort ( short value )
{
assert ( m_position + 1 < m_limit ) ;
if ( byteOrder = = BIGENDIAN )
{
buffer [ m_position ] = ( value > > 8 ) & 0xFF ;
buffer [ m_position + 1 ] = value & 0xFF ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
buffer [ m_position ] = value & 0xFF ;
buffer [ m_position + 1 ] = ( value > > 8 ) & 0xFF ;
}
m_position + = 2 ;
return this ;
}
ByteBuffer * ByteBuffer : : putShortArray ( shortArray & s )
{
// TODO 4J Stu - Should this function be writing from the start of the buffer, or from position?
// And should it update position?
assert ( s . length * 2 < = m_limit ) ;
2026-03-02 17:39:35 +07:00
2026-03-01 12:16:08 +08:00
// 4J Stu - Assumes big endian
memcpy ( buffer , s . data , s . length * 2 ) ;
return this ;
}
//Relative put method for writing a long value (optional operation).
//Writes eight bytes containing the given long value, in the current byte order, into this buffer at the current position,
//and then increments the position by eight.
//
//Parameters:
//value - The long value to be written
//Returns:
//This buffer
2026-03-02 17:39:35 +07:00
ByteBuffer * ByteBuffer : : putLong ( __int64 value )
2026-03-01 12:16:08 +08:00
{
assert ( m_position + 7 < m_limit ) ;
if ( byteOrder = = BIGENDIAN )
{
buffer [ m_position ] = ( value > > 56 ) & 0xFF ;
buffer [ m_position + 1 ] = ( value > > 48 ) & 0xFF ;
buffer [ m_position + 2 ] = ( value > > 40 ) & 0xFF ;
buffer [ m_position + 3 ] = ( value > > 32 ) & 0xFF ;
buffer [ m_position + 4 ] = ( value > > 24 ) & 0xFF ;
buffer [ m_position + 5 ] = ( value > > 16 ) & 0xFF ;
buffer [ m_position + 6 ] = ( value > > 8 ) & 0xFF ;
buffer [ m_position + 7 ] = value & 0xFF ;
}
else if ( byteOrder = = LITTLEENDIAN )
{
buffer [ m_position ] = value & 0xFF ;
buffer [ m_position + 1 ] = ( value > > 8 ) & 0xFF ;
buffer [ m_position + 2 ] = ( value > > 16 ) & 0xFF ;
buffer [ m_position + 3 ] = ( value > > 24 ) & 0xFF ;
buffer [ m_position + 4 ] = ( value > > 32 ) & 0xFF ;
buffer [ m_position + 5 ] = ( value > > 40 ) & 0xFF ;
buffer [ m_position + 6 ] = ( value > > 48 ) & 0xFF ;
buffer [ m_position + 7 ] = ( value > > 56 ) & 0xFF ;
}
return this ;
}
//Relative bulk put method (optional operation).
//This method transfers the entire content of the given source byte array into this buffer.
//An invocation of this method of the form dst.put(a) behaves in exactly the same way as the invocation
//
2026-03-02 17:39:35 +07:00
// dst.put(a, 0, a.length)
2026-03-01 12:16:08 +08:00
//Returns:
//This buffer
ByteBuffer * ByteBuffer : : put ( byteArray inputArray )
{
if ( inputArray . length > remaining ( ) )
assert ( false ) ; //TODO 4J Stu - Some kind of exception?
std : : copy ( inputArray . data , inputArray . data + inputArray . length , buffer + m_position ) ;
m_position + = inputArray . length ;
return this ;
}
byteArray ByteBuffer : : array ( )
{
return byteArray ( buffer , m_capacity ) ;
}
//Creates a view of this byte buffer as an int buffer.
//The content of the new buffer will start at this buffer's current position. Changes to this buffer's content
//will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent.
//
//The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this buffer
//divided by four, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, and
//it will be read-only if, and only if, this buffer is read-only.
//
//Returns:
2026-03-02 17:39:35 +07:00
//A new int buffer
2026-03-01 12:16:08 +08:00
IntBuffer * ByteBuffer : : asIntBuffer ( )
{
// TODO 4J Stu - Is it safe to just cast our byte array pointer to another type?
return new IntBuffer ( ( m_limit - m_position ) / 4 , ( int * ) ( buffer + m_position ) ) ;
}
//Creates a view of this byte buffer as a float buffer.
//The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will be
//visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent.
//
//The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this buffer
//divided by four, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct,
//and it will be read-only if, and only if, this buffer is read-only.
//
//Returns:
//A new float buffer
FloatBuffer * ByteBuffer : : asFloatBuffer ( )
{
// TODO 4J Stu - Is it safe to just cast our byte array pointer to another type?
return new FloatBuffer ( ( m_limit - m_position ) / 4 , ( float * ) ( buffer + m_position ) ) ;
}
# ifdef __PS3__
// we're using the RSX now to upload textures to vram, so we need th main ram textures allocated from io space
2026-03-02 17:39:35 +07:00
ByteBuffer_IO : : ByteBuffer_IO ( unsigned int capacity )
2026-03-01 12:16:08 +08:00
: ByteBuffer ( capacity , ( byte * ) RenderManager . allocIOMem ( capacity , 64 ) )
{
memset ( buffer , 0 , sizeof ( byte ) * capacity ) ;
byteOrder = BIGENDIAN ;
}
ByteBuffer_IO : : ~ ByteBuffer_IO ( )
{
// delete buffer;
RenderManager . freeIOMem ( buffer ) ;
}
# endif // __PS3__