Add file loading to platform layer

This commit is contained in:
Doyle Thai 2017-04-05 17:35:23 +10:00
parent b415f4c237
commit dc8afe349a
6 changed files with 552 additions and 358 deletions

View File

@ -73,7 +73,7 @@
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)\bin\</OutDir> <OutDir>$(SolutionDir)\bin\</OutDir>
<IntDir>$(SolutionDir)\bin\</IntDir> <IntDir>$(SolutionDir)</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>

View File

@ -1,8 +1,23 @@
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "dchip8_platform.h" #include "dchip8_platform.h"
#include "dqnt.h" #include "dqnt.h"
#include "stdio.h"
enum Chip8State
{
chip8state_init,
chip8state_load_file,
chip8state_running,
chip8state_off,
};
typedef struct Chip8CPU typedef struct Chip8CPU
{ {
const u16 INIT_ADDRESS = 0x200;
union { union {
u8 registerArray[16]; u8 registerArray[16];
struct struct
@ -50,10 +65,12 @@ typedef struct Chip8CPU
u8 stackPointer; u8 stackPointer;
u16 stack[16]; u16 stack[16];
bool isInit; enum Chip8State state;
} Chip8CPU; } Chip8CPU;
FILE_SCOPE Chip8CPU cpu; FILE_SCOPE Chip8CPU cpu;
FILE_SCOPE RandPCGState pcgState;
void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
PlatformMemory memory) PlatformMemory memory)
{ {
@ -82,22 +99,46 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
bitmapBuffer[i] = color; bitmapBuffer[i] = color;
} }
if (!cpu.isInit) u8 *mainMem = (u8 *)memory.permanentMem;
if (cpu.state == chip8state_init)
{ {
DQNT_ASSERT(memory.permanentMemSize == (4096 / 4)); DQNT_ASSERT(memory.permanentMemSize == (4096 / 4));
cpu.isInit = true;
// NOTE: Everything before 0x200 is reserved for the actual emulator // NOTE: Everything before 0x200 is reserved for the actual emulator
const u32 INIT_ADDRESS = 0x200; cpu.programCounter = cpu.INIT_ADDRESS;
cpu.programCounter = INIT_ADDRESS;
cpu.I = 0; cpu.I = 0;
cpu.stackPointer = 0; cpu.stackPointer = 0;
// TODO(doyle): Load rom const u32 SEED = 0x8293A8DE;
dqnt_rnd_pcg_seed(&pcgState, SEED);
cpu.state = chip8state_load_file;
} }
#if 0 if (cpu.state == chip8state_load_file)
u8 *mainMem = (u8 *)memory.permanentMem; {
PlatformFile file = {};
if (platform_open_file(L"roms/PONG", &file))
{
DQNT_ASSERT((cpu.INIT_ADDRESS + file.size) <=
DQNT_ARRAY_COUNT(mainMem));
void *loadToAddr = (void *)(&mainMem[cpu.INIT_ADDRESS]);
if (platform_read_file(file, loadToAddr, (u32)file.size))
{
cpu.state = chip8state_running;
}
else
{
cpu.state = chip8state_off;
}
platform_close_file(&file);
}
}
if (cpu.state == chip8state_running)
{
u8 opHighByte = mainMem[cpu.programCounter++]; u8 opHighByte = mainMem[cpu.programCounter++];
u8 opLowByte = mainMem[cpu.programCounter++]; u8 opLowByte = mainMem[cpu.programCounter++];
@ -201,7 +242,6 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
DQNT_ASSERT(opFirstNibble == 0x70); DQNT_ASSERT(opFirstNibble == 0x70);
cpu.registerArray[regNum] += valToOperateOn; cpu.registerArray[regNum] += valToOperateOn;
} }
} }
break; break;
@ -246,7 +286,6 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
*vx = (u8)result; *vx = (u8)result;
if (result > 255) cpu.VF = (result > 255) ? 1 : 0; if (result > 255) cpu.VF = (result > 255) ? 1 : 0;
} }
// SUB Vx, Vy - 8xy5 - Set Vx = Vx - Vy, set VF = NOT borrow // SUB Vx, Vy - 8xy5 - Set Vx = Vx - Vy, set VF = NOT borrow
else if (opLowByte == 0x05) else if (opLowByte == 0x05)
@ -333,8 +372,8 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
u8 andBits = opLowByte; u8 andBits = opLowByte;
u8 *vx = &cpu.registerArray[firstRegNum]; u8 *vx = &cpu.registerArray[firstRegNum];
// TODO(doyle): Random umber u8 randNum = (u8)dqnt_rnd_pcg_range(&pcgState, 0, 255);
*vx = (28 & opLowByte); *vx = (randNum & opLowByte);
} }
break; break;
@ -351,13 +390,15 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
// TODO(doyle): Implement key checks // TODO(doyle): Implement key checks
u8 checkKey = (0x0F & opHighByte); u8 checkKey = (0x0F & opHighByte);
// SKP Vx - Ex9E - Skip next instruction if key with the value of Vx // SKP Vx - Ex9E - Skip next instruction if key with the value
// of Vx
// is pressed // is pressed
bool skipNextInstruction = false; bool skipNextInstruction = false;
if (opLowByte == 0x9E) if (opLowByte == 0x9E)
{ {
} }
// SKNP Vx - ExA1 - Skip next instruction if key with the value of // SKNP Vx - ExA1 - Skip next instruction if key with the value
// of
// Vx is not pressed // Vx is not pressed
else else
{ {
@ -379,8 +420,8 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
{ {
*vx = cpu.delayTimer; *vx = cpu.delayTimer;
} }
// LD Vx, K - Fx0A - Wait for a key press, store the value of the // LD Vx, K - Fx0A - Wait for a key press, store the value of
// key in Vx // the key in Vx
else if (opLowByte == 0x0A) else if (opLowByte == 0x0A)
{ {
} }
@ -435,5 +476,6 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
} }
break; break;
}; };
#endif }
} }

View File

@ -53,4 +53,16 @@ typedef struct PlatformMemory
u32 transientMemSize; u32 transientMemSize;
} PlatformMemory; } PlatformMemory;
typedef struct PlatformFile
{
void *handle;
u64 size;
} PlatformFile;
// Return true if successful, false if not
bool platform_open_file (const wchar_t *const file, PlatformFile *platformFile);
// Return the number of bytes read
u32 platform_read_file (PlatformFile file, void *buffer, u32 numBytesToRead);
void platform_close_file(PlatformFile *file);
#endif #endif

View File

@ -50,8 +50,17 @@ v2 V2i(i32 x, i32 y);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// String Ops // String Ops
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool dqnt_char_is_digit (char c);
bool dqnt_char_is_alpha (char c);
bool dqnt_char_is_alphanum(char c);
i32 dqnt_strcmp (const char *a, const char *b); i32 dqnt_strcmp (const char *a, const char *b);
// Returns the length without the null terminator
i32 dqnt_strlen (const char *a); i32 dqnt_strlen (const char *a);
char *dqnt_strncpy(char *dest, const char *src, i32 numChars);
bool dqnt_str_reverse(char *const buf, const i32 bufSize);
i32 dqnt_str_to_i32 (char *const buf, const i32 bufSize);
wchar_t dqnt_wchar_ascii_to_lower(wchar_t character); wchar_t dqnt_wchar_ascii_to_lower(wchar_t character);
i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b); i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b);
@ -70,6 +79,8 @@ typedef struct RandPCGState
void dqnt_rnd_pcg_seed (RandPCGState *pcg, u32 seed); void dqnt_rnd_pcg_seed (RandPCGState *pcg, u32 seed);
// Returns a random number N between [0, 0xFFFFFFFF] // Returns a random number N between [0, 0xFFFFFFFF]
u32 dqnt_rnd_pcg_next (RandPCGState *pcg); u32 dqnt_rnd_pcg_next (RandPCGState *pcg);
// Returns a random float N between [0.0, 1.0f]
f32 dqnt_rnd_pcg_nextf(RandPCGState *pcg);
// Returns a random integer N between [min, max] // Returns a random integer N between [min, max]
i32 dqnt_rnd_pcg_range(RandPCGState *pcg, i32 min, i32 max); i32 dqnt_rnd_pcg_range(RandPCGState *pcg, i32 min, i32 max);
@ -98,6 +109,24 @@ v2 V2i(i32 x, i32 y)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// String Ops // String Ops
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool dqnt_char_is_digit(char c)
{
if (c >= '0' && c <= '9') return true;
return false;
}
bool dqnt_char_is_alpha(char c)
{
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return true;
return false;
}
bool dqnt_char_is_alphanum(char c)
{
if (dqnt_char_is_alpha(c) || dqnt_char_is_digit(c)) return true;
return false;
}
i32 dqnt_strcmp(const char *a, const char *b) i32 dqnt_strcmp(const char *a, const char *b)
{ {
while ((*a) == (*b)) while ((*a) == (*b))
@ -110,6 +139,86 @@ i32 dqnt_strcmp(const char *a, const char *b)
return (((*a) < (*b)) ? -1 : 1); return (((*a) < (*b)) ? -1 : 1);
} }
i32 dqnt_strlen(const char *a)
{
i32 result = 0;
while (a[result]) result++;
return result;
}
char *dqnt_strncpy(char *dest, const char *src, i32 numChars)
{
if (!dest) return NULL;
if (!src) return dest;
for (i32 i = 0; i < numChars; i++)
dest[i] = src[i];
return dest;
}
bool dqnt_str_reverse(char *const buf, const i32 bufSize)
{
if (!buf) return false;
i32 mid = bufSize / 2;
for (i32 i = 0; i < mid; i++)
{
char tmp = buf[i];
buf[i] = buf[(bufSize - 1) - i];
buf[(bufSize - 1) - i] = tmp;
}
return true;
}
i32 dqnt_str_to_i32(char *const buf, const i32 bufSize)
{
if (!buf || bufSize == 0) return 0;
i32 index = 0;
bool isNegative = false;
if (buf[index] == '-' || buf[index] == '+')
{
if (buf[index] == '-') isNegative = true;
index++;
}
else if (!dqnt_char_is_digit(buf[index]))
{
return 0;
}
i32 result = 0;
for (i32 i = index; i < bufSize; i++)
{
if (dqnt_char_is_digit(buf[i]))
{
result *= 10;
result += (buf[i] - '0');
}
else
{
break;
}
}
if (isNegative) result *= -1;
return result;
}
wchar_t dqnt_wchar_ascii_to_lower(wchar_t character)
{
if (character >= L'A' && character <= L'Z')
{
i32 shiftOffset = L'a' - L'A';
character += (wchar_t)shiftOffset;
}
return character;
}
i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b) i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b)
{ {
while ((*a) == (*b)) while ((*a) == (*b))
@ -137,17 +246,6 @@ void dqnt_wstrcat(const wchar_t *a, i32 lenA, const wchar_t *b, i32 lenB,
DQNT_ASSERT(outIndex <= outLen); DQNT_ASSERT(outIndex <= outLen);
} }
wchar_t dqnt_wchar_ascii_to_lower(wchar_t character)
{
if (character >= L'A' && character <= L'Z')
{
i32 shiftOffset = L'a' - L'A';
character += (wchar_t)shiftOffset;
}
return character;
}
i32 dqnt_wstrlen(const wchar_t *a) i32 dqnt_wstrlen(const wchar_t *a)
{ {
i32 result = 0; i32 result = 0;
@ -160,18 +258,6 @@ i32 dqnt_wstrlen(const wchar_t *a)
return result; return result;
} }
i32 dqnt_strlen(const char *a)
{
i32 result = 0;
while ((*a))
{
result++;
a++;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// PCG (Permuted Congruential Generator) Random Number Generator // PCG (Permuted Congruential Generator) Random Number Generator
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -180,7 +266,7 @@ i32 dqnt_strlen(const char *a)
// Convert a randomized u32 value to a float value x in the range 0.0f <= x // Convert a randomized u32 value to a float value x in the range 0.0f <= x
// < 1.0f. Contributed by Jonatan Hedborg // < 1.0f. Contributed by Jonatan Hedborg
FILE_SCOPE f32 dqnt_rnd_f32_normalized_from_u32_(u32 value) FILE_SCOPE f32 dqnt_rnd_f32_normalized_from_u32_internal(u32 value)
{ {
u32 exponent = 127; u32 exponent = 127;
u32 mantissa = value >> 9; u32 mantissa = value >> 9;
@ -189,7 +275,7 @@ FILE_SCOPE f32 dqnt_rnd_f32_normalized_from_u32_(u32 value)
return fresult - 1.0f; return fresult - 1.0f;
} }
FILE_SCOPE u64 dqnt_rnd_murmur3_avalanche64_(u64 h) FILE_SCOPE u64 dqnt_rnd_murmur3_avalanche64_internal(u64 h)
{ {
h ^= h >> 33; h ^= h >> 33;
h *= 0xff51afd7ed558ccd; h *= 0xff51afd7ed558ccd;
@ -202,11 +288,11 @@ FILE_SCOPE u64 dqnt_rnd_murmur3_avalanche64_(u64 h)
void dqnt_rnd_pcg_seed(RandPCGState *pcg, u32 seed) void dqnt_rnd_pcg_seed(RandPCGState *pcg, u32 seed)
{ {
u64 value = (((u64)seed) << 1ULL) | 1ULL; u64 value = (((u64)seed) << 1ULL) | 1ULL;
value = dqnt_rnd_murmur3_avalanche64_(value); value = dqnt_rnd_murmur3_avalanche64_internal(value);
pcg->state[0] = 0U; pcg->state[0] = 0U;
pcg->state[1] = (value << 1ULL) | 1ULL; pcg->state[1] = (value << 1ULL) | 1ULL;
dqnt_rnd_pcg_next(pcg); dqnt_rnd_pcg_next(pcg);
pcg->state[0] += dqnt_rnd_murmur3_avalanche64_(value); pcg->state[0] += dqnt_rnd_murmur3_avalanche64_internal(value);
dqnt_rnd_pcg_next(pcg); dqnt_rnd_pcg_next(pcg);
} }
@ -221,7 +307,7 @@ u32 dqnt_rnd_pcg_next(RandPCGState *pcg)
f32 dqnt_rnd_pcg_nextf(RandPCGState *pcg) f32 dqnt_rnd_pcg_nextf(RandPCGState *pcg)
{ {
return dqnt_rnd_f32_normalized_from_u32_(dqnt_rnd_pcg_next(pcg)); return dqnt_rnd_f32_normalized_from_u32_internal(dqnt_rnd_pcg_next(pcg));
} }
i32 dqnt_rnd_pcg_range(RandPCGState *pcg, i32 min, i32 max) i32 dqnt_rnd_pcg_range(RandPCGState *pcg, i32 min, i32 max)

View File

@ -1,3 +1,5 @@
#define _CRT_SECURE_NO_WARNINGS
#define DQNT_IMPLEMENTATION #define DQNT_IMPLEMENTATION
#include "dqnt.h" #include "dqnt.h"

View File

@ -300,3 +300,55 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
return 0; return 0;
} }
void platform_close_file(PlatformFile *file)
{
CloseHandle(file->handle);
file->handle = NULL;
file->size = 0;
}
u32 platform_read_file(PlatformFile file, void *buffer, u32 numBytesToRead)
{
DWORD numBytesRead = 0;
if (file.handle && buffer)
{
HANDLE win32Handle = file.handle;
BOOL result =
ReadFile(win32Handle, buffer, numBytesToRead, &numBytesRead, NULL);
// TODO(doyle): 0 also means it is completing async, but still valid
if (result == 0)
{
win32_error_box(L"ReadFile() failed.", nullptr);
}
}
return numBytesRead;
}
FILE_SCOPE u32 buffer[15000];
bool platform_open_file(const wchar_t *const file, PlatformFile *platformFile)
{
HANDLE handle = CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
win32_error_box(L"CreateFile() failed.", nullptr);
return false;
}
LARGE_INTEGER size;
if (GetFileSizeEx(handle, &size) == 0)
{
win32_error_box(L"GetFileSizeEx() failed.", nullptr);
return false;
}
platformFile->handle = handle;
platformFile->size = size.QuadPart;
return true;
}