diff --git a/gbemu/gbemu/common/emusys.h b/gbemu/gbemu/common/emusys.h new file mode 100644 index 0000000..a976d32 --- /dev/null +++ b/gbemu/gbemu/common/emusys.h @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +typedef unsigned char byte; +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned int uint; +typedef signed long long int64; +typedef unsigned long long uint64; \ No newline at end of file diff --git a/gbemu/gbemu/common/endianness.h b/gbemu/gbemu/common/endianness.h new file mode 100644 index 0000000..1847f50 --- /dev/null +++ b/gbemu/gbemu/common/endianness.h @@ -0,0 +1,99 @@ +#include "emusys.h" + +// Below macros are used for converting +// Little Endian data to Big Endian and vice versa +// This uses MSVC's and GCC's stdlib header +// Using inline implmentations for other compilers +#if defined(__GNUC__) + #define SWAP_BYTES_64(a) __builtin_bswap64(a) + #define SWAP_BYTES_32(a) __builtin_bswap32(a) + #define SWAP_BYTES_16(a) __builtin_bswap16(a) +#elif defined(_MSC_VER) + #define SWAP_BYTES_64(a) _byteswap_uint64(a) + #define SWAP_BYTES_32(a) _byteswap_ulong(a) + #define SWAP_BYTES_16(a) _byteswap_ushort(a) +#else + inline uint64 SWAP_BYTES_64(uint64 a) { + uint32 low = (uint32)a, high = (uint32)(a >> 32); + uint16 lowLow = (uint16)low, lowHigh = (uint16)(low >> 16), highLow = (uint16)high, highHigh = (uint16)(high >> 16); + + return ((uint64)(((uint32)(uint16)((lowLow >> 8) | (lowLow << 8)) << 16) | (uint16)((lowHigh >> 8) | (lowHigh << 8))) << 32) | (((uint32)(uint16)((highLow >> 8) | (highLow << 8)) << 16) | (uint16)((highHigh >> 8) | (highHigh << 8))); + } + inline uint32 SWAP_BYTES_32(uint32 a) { + const uint16 low = (uint16)a, high = (uint16)(a >> 16); + return ((uint32)(uint16)((low >> 8) | (low << 8)) << 16) | (uint16)((high >> 8) | (high << 8)); + } + inline uint16 SWAP_BYTES_16(const uint16 a) { + return (a >> 8) | (a << 8); + } +#endif + + +// We assume the machine to be Little Endian by default +// As this is running on Intel, AMD and Apple Silicon chips +// Will add compatibility for Big Endian machine later + +inline uint16 READ_UINT16(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[1] << 8) | b[0]; +} + +inline uint32 READ_UINT32(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]); +} + +inline uint64 READ_UINT64(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return ((uint64)b[7] << 56) | ((uint64)b[6] << 48) | ((uint64)b[5] << 40) | ((uint64)b[4] << 32) | ((uint64)b[3] << 24) | ((uint64)b[2] << 16) | ((uint64)b[1] << 8) | ((uint64)b[0]); +} + +inline void WRITE_UINT16(void *ptr, uint16 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); +} + +inline void WRITE_UINT32(void *ptr, uint32 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); + b[2] = (uint8)(value >> 16); + b[3] = (uint8)(value >> 24); +} + +inline void WRITE_UINT64(void *ptr, uint64 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); + b[2] = (uint8)(value >> 16); + b[3] = (uint8)(value >> 24); + b[4] = (uint8)(value >> 32); + b[5] = (uint8)(value >> 40); + b[6] = (uint8)(value >> 48); + b[7] = (uint8)(value >> 56); +} + +// Used in Common::Stream +#define READ_LE_UINT16(a) READ_UINT16(a) +#define READ_LE_UINT32(a) READ_UINT32(a) +#define READ_LE_UINT64(a) READ_UINT64(a) +#define WRITE_LE_UINT16(a, v) WRITE_UINT16(a, v) +#define WRITE_LE_UINT32(a, v) WRITE_UINT32(a, v) +#define WRITE_LE_UINT64(a, v) WRITE_UINT64(a, v) +#define FROM_LE_16(a) ((uint16)(a)) +#define FROM_LE_32(a) ((uint32)(a)) +#define FROM_LE_64(a) ((uint64)(a)) +#define FROM_BE_16(a) SWAP_BYTES_16(a) +#define FROM_BE_32(a) SWAP_BYTES_32(a) +#define FROM_BE_64(a) SWAP_BYTES_64(a) +#define TO_LE_16(a) ((uint16)(a)) +#define TO_LE_32(a) ((uint32)(a)) +#define TO_LE_64(a) ((uint64)(a)) +#define TO_BE_16(a) SWAP_BYTES_16(a) +#define TO_BE_32(a) SWAP_BYTES_32(a) +#define TO_BE_64(a) SWAP_BYTES_64(a) + +// Might come handy later +#define LITTLE_ENDIAN false +#define BIG_ENDIAN true \ No newline at end of file diff --git a/gbemu/gbemu/common/stream.h b/gbemu/gbemu/common/stream.h new file mode 100644 index 0000000..44f2a5e --- /dev/null +++ b/gbemu/gbemu/common/stream.h @@ -0,0 +1,88 @@ +//Taken from ScummVM's Common::Stream + +#include "endianness.h" + +namespace Common { + class Stream { + public: + virtual ~Stream() {} + + // Below functions throw error and reset the error flag + // Similar to ferror() and clearerr() + + virtual bool err() const { return false; } + virtual void clearError() {} + }; + + class ReadStream : virtual public Stream { + private: + bool isBigEndian; + + public: + ReadStream(bool bigEndian = LITTLE_ENDIAN) : isBigEndian(bigEndian) {} + + bool isBE() { return isBigEndian; } + + // End of stream interface + virtual bool eos() const = 0; + + // Read interface + virtual uint32 read(void *dataPtr, uint32 dataSize) = 0; + + byte readByte() { + byte b = 0; + read(&b, 1); + return b; + } + + uint16 readUint16() { + uint16 val; + read(&val, 2); + return (isBigEndian) ? FROM_BE_16(val) : FROM_LE_16(val); + } + + uint32 readUint32() { + uint32 val; + read(&val, 4); + return (isBigEndian) ? FROM_BE_32(val) : FROM_LE_32(val); + } + + uint64 readUint64() { + uint64 val; + read(&val, 8); + return (isBigEndian) ? FROM_BE_64(val) : FROM_LE_64(val); + } + + inline byte readSByte() { + return (int8) readByte(); + } + + inline int16 readSint16() { + return (int16) readUint16(); + } + + inline int32 readSint32() { + return (int32) readUint32(); + } + + inline int64 readSint64() { + return (int64) readUint64(); + } + }; + + class SeekableReadStream : virtual public ReadStream { + public: + // Position of cursor + virtual int64 pos() const = 0; + + // Size of stream + virtual int64 size() const = 0; + + // Set the cursor to a specific place in stream + // wrapper identical to fseek() + virtual bool seek(int64 offset, int whence = SEEK_SET) = 0; + + // Skip given bytes in stream + virtual bool skip(uint32 offset) { return seek(offset, SEEK_CUR); } + }; +} \ No newline at end of file diff --git a/gbemu/gbemu/gbemu.cpp b/gbemu/gbemu/gbemu.cpp new file mode 100644 index 0000000..1ed8e48 --- /dev/null +++ b/gbemu/gbemu/gbemu.cpp @@ -0,0 +1,20 @@ +#include "common/stream.h" + +int main() +{ + char* k = new char[10]; + printf_s("Hello World\n"); + scanf_s(k); + return 0; +} + +// Run program: Ctrl + F5 or Debug > Start Without Debugging menu +// Debug program: F5 or Debug > Start Debugging menu + +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file