Start using dqnt lib
This commit is contained in:
parent
dff3495087
commit
b415f4c237
127
src/Common.h
127
src/Common.h
@ -1,127 +0,0 @@
|
|||||||
#ifndef COMMON_H
|
|
||||||
#define COMMON_H
|
|
||||||
|
|
||||||
#include "stdint.h"
|
|
||||||
|
|
||||||
#define LOCAL_PERSIST static
|
|
||||||
#define FILE_SCOPE static
|
|
||||||
|
|
||||||
typedef uint32_t u32;
|
|
||||||
typedef uint16_t u16;
|
|
||||||
typedef uint8_t u8;
|
|
||||||
|
|
||||||
typedef int64_t i64;
|
|
||||||
typedef int32_t i32;
|
|
||||||
typedef int16_t i16;
|
|
||||||
|
|
||||||
typedef float f32;
|
|
||||||
|
|
||||||
#define INVALID_CODE_PATH 0
|
|
||||||
|
|
||||||
#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
|
|
||||||
|
|
||||||
#ifdef DEBUG_MODE
|
|
||||||
#define ASSERT(expr) if (!(expr)) { (*((int *)0)) = 0; }
|
|
||||||
#else
|
|
||||||
#define ASSERT(expr)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MATH_ABS(x) (((x) < 0) ? (-(x)) : (x))
|
|
||||||
|
|
||||||
typedef union v2 {
|
|
||||||
struct { f32 x, y; };
|
|
||||||
struct { f32 w, h; };
|
|
||||||
} v2;
|
|
||||||
|
|
||||||
inline FILE_SCOPE v2 V2(f32 x, f32 y)
|
|
||||||
{
|
|
||||||
v2 result = {};
|
|
||||||
result.x = x;
|
|
||||||
result.y = y;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE v2 V2i(i32 x, i32 y)
|
|
||||||
{
|
|
||||||
v2 result = V2((f32)x, (f32)y);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE i32 common_strcmp(const char *a, const char *b)
|
|
||||||
{
|
|
||||||
while ((*a) == (*b))
|
|
||||||
{
|
|
||||||
if (!(*a)) return 0;
|
|
||||||
a++;
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (((*a) < (*b)) ? -1 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE i32 common_wstrcmp(const wchar_t *a, const wchar_t *b)
|
|
||||||
{
|
|
||||||
while ((*a) == (*b))
|
|
||||||
{
|
|
||||||
if (!(*a)) return 0;
|
|
||||||
a++;
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (((*a) < (*b)) ? -1 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE void common_wstrcat(const wchar_t *a, i32 lenA,
|
|
||||||
const wchar_t *b, i32 lenB, wchar_t *out,
|
|
||||||
i32 outLen)
|
|
||||||
{
|
|
||||||
ASSERT((lenA + lenB) < outLen);
|
|
||||||
|
|
||||||
i32 outIndex = 0;
|
|
||||||
for (i32 i = 0; i < lenA; i++)
|
|
||||||
out[outIndex++] = a[i];
|
|
||||||
|
|
||||||
for (i32 i = 0; i < lenB; i++)
|
|
||||||
out[outIndex++] = b[i];
|
|
||||||
|
|
||||||
ASSERT(outIndex <= outLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE wchar_t common_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE i32 common_wstrlen(const wchar_t *a)
|
|
||||||
{
|
|
||||||
i32 result = 0;
|
|
||||||
while ((*a))
|
|
||||||
{
|
|
||||||
result++;
|
|
||||||
a++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FILE_SCOPE i32 common_strlen(const char *a)
|
|
||||||
{
|
|
||||||
i32 result = 0;
|
|
||||||
while ((*a))
|
|
||||||
{
|
|
||||||
result++;
|
|
||||||
a++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||||||
#include "common.h"
|
|
||||||
#include "dchip8_platform.h"
|
#include "dchip8_platform.h"
|
||||||
|
#include "dqnt.h"
|
||||||
|
|
||||||
typedef struct Chip8CPU
|
typedef struct Chip8CPU
|
||||||
{
|
{
|
||||||
@ -54,15 +54,13 @@ typedef struct Chip8CPU
|
|||||||
} Chip8CPU;
|
} Chip8CPU;
|
||||||
|
|
||||||
FILE_SCOPE Chip8CPU cpu;
|
FILE_SCOPE Chip8CPU cpu;
|
||||||
FILE_SCOPE u16 opCodes[35];
|
|
||||||
|
|
||||||
void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
||||||
PlatformMemory memory)
|
PlatformMemory memory)
|
||||||
{
|
{
|
||||||
ASSERT(indexRegister >= 0 && indexRegister <= 0xFFF);
|
DQNT_ASSERT(indexRegister >= 0 && indexRegister <= 0xFFF);
|
||||||
ASSERT(programCounter >= 0 && programCounter <= 0xFFF);
|
DQNT_ASSERT(programCounter >= 0 && programCounter <= 0xFFF);
|
||||||
|
|
||||||
ASSERT(renderBuffer.bytesPerPixel == 4);
|
DQNT_ASSERT(renderBuffer.bytesPerPixel == 4);
|
||||||
|
|
||||||
const i32 numPixels = renderBuffer.width * renderBuffer.height;
|
const i32 numPixels = renderBuffer.width * renderBuffer.height;
|
||||||
u32 *bitmapBuffer = (u32 *)renderBuffer.memory;
|
u32 *bitmapBuffer = (u32 *)renderBuffer.memory;
|
||||||
@ -86,7 +84,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
|
|
||||||
if (!cpu.isInit)
|
if (!cpu.isInit)
|
||||||
{
|
{
|
||||||
ASSERT(memory.permanentMemSize == (4096 / 4));
|
DQNT_ASSERT(memory.permanentMemSize == (4096 / 4));
|
||||||
cpu.isInit = true;
|
cpu.isInit = true;
|
||||||
|
|
||||||
// NOTE: Everything before 0x200 is reserved for the actual emulator
|
// NOTE: Everything before 0x200 is reserved for the actual emulator
|
||||||
@ -94,8 +92,11 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
cpu.programCounter = INIT_ADDRESS;
|
cpu.programCounter = INIT_ADDRESS;
|
||||||
cpu.I = 0;
|
cpu.I = 0;
|
||||||
cpu.stackPointer = 0;
|
cpu.stackPointer = 0;
|
||||||
|
|
||||||
|
// TODO(doyle): Load rom
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
u8 *mainMem = (u8 *)memory.permanentMem;
|
u8 *mainMem = (u8 *)memory.permanentMem;
|
||||||
u8 opHighByte = mainMem[cpu.programCounter++];
|
u8 opHighByte = mainMem[cpu.programCounter++];
|
||||||
u8 opLowByte = mainMem[cpu.programCounter++];
|
u8 opLowByte = mainMem[cpu.programCounter++];
|
||||||
@ -121,7 +122,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0x20:
|
case 0x20:
|
||||||
{
|
{
|
||||||
u16 loc = ((0x0F & opHighByte) << 8) | (0xFF & opLowByte);
|
u16 loc = ((0x0F & opHighByte) << 8) | (0xFF & opLowByte);
|
||||||
ASSERT(loc <= 0x0FFF);
|
DQNT_ASSERT(loc <= 0x0FFF);
|
||||||
|
|
||||||
// JP addr - 1nnn - Jump to location nnn
|
// JP addr - 1nnn - Jump to location nnn
|
||||||
if (opFirstNibble == 0x10)
|
if (opFirstNibble == 0x10)
|
||||||
@ -131,10 +132,10 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
// Call addr - 2nnn - Call subroutine at nnn
|
// Call addr - 2nnn - Call subroutine at nnn
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(opFirstNibble == 0x20);
|
DQNT_ASSERT(opFirstNibble == 0x20);
|
||||||
|
|
||||||
cpu.stackPointer++;
|
cpu.stackPointer++;
|
||||||
ASSERT(cpu.stackPointer < ARRAY_COUNT(cpu.stack));
|
DQNT_ASSERT(cpu.stackPointer < DQNT_ARRAY_COUNT(cpu.stack));
|
||||||
cpu.stack[cpu.stackPointer] = cpu.programCounter;
|
cpu.stack[cpu.stackPointer] = cpu.programCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +147,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0x40:
|
case 0x40:
|
||||||
{
|
{
|
||||||
u8 regNum = (0x0F & opHighByte);
|
u8 regNum = (0x0F & opHighByte);
|
||||||
ASSERT(regNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
u8 valToCheck = opLowByte;
|
u8 valToCheck = opLowByte;
|
||||||
|
|
||||||
// SE Vx, byte - 3xkk - Skip next instruction if Vx == kk
|
// SE Vx, byte - 3xkk - Skip next instruction if Vx == kk
|
||||||
@ -158,7 +159,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
// SNE Vx, byte - 4xkk - Skip next instruction if Vx == kk
|
// SNE Vx, byte - 4xkk - Skip next instruction if Vx == kk
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(opFirstNibble == 0x40);
|
DQNT_ASSERT(opFirstNibble == 0x40);
|
||||||
if (cpu.registerArray[regNum] != valToCheck)
|
if (cpu.registerArray[regNum] != valToCheck)
|
||||||
cpu.programCounter += 2;
|
cpu.programCounter += 2;
|
||||||
}
|
}
|
||||||
@ -169,10 +170,10 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0x50:
|
case 0x50:
|
||||||
{
|
{
|
||||||
u8 firstRegNum = (0x0F & opHighByte);
|
u8 firstRegNum = (0x0F & opHighByte);
|
||||||
ASSERT(firstRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(firstRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
u8 secondRegNum = (0xF0 & opLowByte);
|
u8 secondRegNum = (0xF0 & opLowByte);
|
||||||
ASSERT(secondRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(secondRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
if (cpu.registerArray[firstRegNum] ==
|
if (cpu.registerArray[firstRegNum] ==
|
||||||
cpu.registerArray[secondRegNum])
|
cpu.registerArray[secondRegNum])
|
||||||
@ -186,7 +187,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0x70:
|
case 0x70:
|
||||||
{
|
{
|
||||||
u8 regNum = (0x0F & opHighByte);
|
u8 regNum = (0x0F & opHighByte);
|
||||||
ASSERT(regNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
u8 valToOperateOn = opLowByte;
|
u8 valToOperateOn = opLowByte;
|
||||||
|
|
||||||
// LD Vx, byte - 6xkk - Set Vx = kk
|
// LD Vx, byte - 6xkk - Set Vx = kk
|
||||||
@ -197,7 +198,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
// ADD Vx, byte - 7xkk - Set Vx = Vx + kk
|
// ADD Vx, byte - 7xkk - Set Vx = Vx + kk
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(opFirstNibble == 0x70);
|
DQNT_ASSERT(opFirstNibble == 0x70);
|
||||||
cpu.registerArray[regNum] += valToOperateOn;
|
cpu.registerArray[regNum] += valToOperateOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,10 +208,10 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0x80:
|
case 0x80:
|
||||||
{
|
{
|
||||||
u8 firstRegNum = (0x0F & opHighByte);
|
u8 firstRegNum = (0x0F & opHighByte);
|
||||||
ASSERT(firstRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(firstRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
u8 secondRegNum = (0xF0 & opLowByte);
|
u8 secondRegNum = (0xF0 & opLowByte);
|
||||||
ASSERT(secondRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(secondRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
u8 *vx = &cpu.registerArray[firstRegNum];
|
u8 *vx = &cpu.registerArray[firstRegNum];
|
||||||
u8 *vy = &cpu.registerArray[secondRegNum];
|
u8 *vy = &cpu.registerArray[secondRegNum];
|
||||||
@ -280,7 +281,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
// SHL Vx {, Vy} - 8xyE - Set Vx = SHL 1
|
// SHL Vx {, Vy} - 8xyE - Set Vx = SHL 1
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(opLowByte == 0x0E);
|
DQNT_ASSERT(opLowByte == 0x0E);
|
||||||
if ((*vx >> 7) == 1)
|
if ((*vx >> 7) == 1)
|
||||||
cpu.VF = 1;
|
cpu.VF = 1;
|
||||||
else
|
else
|
||||||
@ -295,10 +296,10 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0x90:
|
case 0x90:
|
||||||
{
|
{
|
||||||
u8 firstRegNum = (0x0F & opHighByte);
|
u8 firstRegNum = (0x0F & opHighByte);
|
||||||
ASSERT(firstRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(firstRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
u8 secondRegNum = (0xF0 & opLowByte);
|
u8 secondRegNum = (0xF0 & opLowByte);
|
||||||
ASSERT(secondRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(secondRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
u8 *vx = &cpu.registerArray[firstRegNum];
|
u8 *vx = &cpu.registerArray[firstRegNum];
|
||||||
u8 *vy = &cpu.registerArray[secondRegNum];
|
u8 *vy = &cpu.registerArray[secondRegNum];
|
||||||
@ -327,7 +328,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0xC0:
|
case 0xC0:
|
||||||
{
|
{
|
||||||
u8 firstRegNum = (0x0F & opHighByte);
|
u8 firstRegNum = (0x0F & opHighByte);
|
||||||
ASSERT(firstRegNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(firstRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
|
|
||||||
u8 andBits = opLowByte;
|
u8 andBits = opLowByte;
|
||||||
u8 *vx = &cpu.registerArray[firstRegNum];
|
u8 *vx = &cpu.registerArray[firstRegNum];
|
||||||
@ -360,7 +361,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
// Vx is not pressed
|
// Vx is not pressed
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(opLowByte == 0xA1);
|
DQNT_ASSERT(opLowByte == 0xA1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skipNextInstruction) cpu.programCounter += 2;
|
if (skipNextInstruction) cpu.programCounter += 2;
|
||||||
@ -370,7 +371,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
case 0xF0:
|
case 0xF0:
|
||||||
{
|
{
|
||||||
u8 regNum = (0x0F & opHighByte);
|
u8 regNum = (0x0F & opHighByte);
|
||||||
ASSERT(regNum < ARRAY_COUNT(cpu.registerArray));
|
DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
|
||||||
u8 *vx = &cpu.registerArray[regNum];
|
u8 *vx = &cpu.registerArray[regNum];
|
||||||
|
|
||||||
// LD Vx, DT - Fx07 - Set Vx = delay timer value
|
// LD Vx, DT - Fx07 - Set Vx = delay timer value
|
||||||
@ -423,7 +424,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
// starting at location I.
|
// starting at location I.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(opLowByte == 0x65);
|
DQNT_ASSERT(opLowByte == 0x65);
|
||||||
for (u32 regIndex = 0; regIndex <= regNum; regIndex++)
|
for (u32 regIndex = 0; regIndex <= regNum; regIndex++)
|
||||||
{
|
{
|
||||||
u32 mem_offset = regIndex;
|
u32 mem_offset = regIndex;
|
||||||
@ -434,4 +435,5 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef DCHIP_8_PLATFORM
|
#ifndef DCHIP_8_PLATFORM
|
||||||
#define DCHIP_8_PLATFORM
|
#define DCHIP_8_PLATFORM
|
||||||
|
|
||||||
#include "Common.h"
|
#include "dqnt.h"
|
||||||
|
|
||||||
typedef struct PlatformRenderBuffer
|
typedef struct PlatformRenderBuffer
|
||||||
{
|
{
|
||||||
|
235
src/dqnt.h
Normal file
235
src/dqnt.h
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
#ifndef DQNT_H
|
||||||
|
#define DQNT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define DQNT_IMPLEMENTATION
|
||||||
|
#include "dqnt.h"
|
||||||
|
*/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// General Purpose Operations
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include "stdint.h"
|
||||||
|
#define LOCAL_PERSIST static
|
||||||
|
#define FILE_SCOPE static
|
||||||
|
|
||||||
|
typedef uint64_t u64;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint8_t u8;
|
||||||
|
|
||||||
|
typedef int32_t i64;
|
||||||
|
typedef int32_t i32;
|
||||||
|
typedef int64_t i16;
|
||||||
|
|
||||||
|
typedef float f32;
|
||||||
|
|
||||||
|
#define DQNT_INVALID_CODE_PATH 0
|
||||||
|
#define DQNT_ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
|
||||||
|
|
||||||
|
#ifdef DEBUG_MODE
|
||||||
|
#define DQNT_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; }
|
||||||
|
#else
|
||||||
|
#define DQNT_ASSERT(expr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DQNT_MATH_ABS(x) (((x) < 0) ? (-(x)) : (x))
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Vec2
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef union v2 {
|
||||||
|
struct { f32 x, y; };
|
||||||
|
struct { f32 w, h; };
|
||||||
|
} v2;
|
||||||
|
|
||||||
|
v2 V2(f32 x, f32 y);
|
||||||
|
// Create a 2d-vector using ints and typecast to floats
|
||||||
|
v2 V2i(i32 x, i32 y);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// String Ops
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
i32 dqnt_strcmp(const char *a, const char *b);
|
||||||
|
i32 dqnt_strlen(const char *a);
|
||||||
|
|
||||||
|
wchar_t dqnt_wchar_ascii_to_lower(wchar_t character);
|
||||||
|
i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b);
|
||||||
|
void dqnt_wstrcat(const wchar_t *a, i32 lenA, const wchar_t *b, i32 lenB, wchar_t *out, i32 outLen);
|
||||||
|
i32 dqnt_wstrlen(const wchar_t *a);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PCG (Permuted Congruential Generator) Random Number Generator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef struct RandPCGState
|
||||||
|
{
|
||||||
|
u64 state[2];
|
||||||
|
} RandPCGState;
|
||||||
|
|
||||||
|
// Init generator with seed. The generator is not valid until it's been seeded.
|
||||||
|
void dqnt_rnd_pcg_seed (RandPCGState *pcg, u32 seed);
|
||||||
|
// Returns a random number N between [0, 0xFFFFFFFF]
|
||||||
|
u32 dqnt_rnd_pcg_next (RandPCGState *pcg);
|
||||||
|
// Returns a random integer N between [min, max]
|
||||||
|
i32 dqnt_rnd_pcg_range(RandPCGState *pcg, i32 min, i32 max);
|
||||||
|
|
||||||
|
#endif /* DQNT_H */
|
||||||
|
|
||||||
|
#ifdef DQNT_IMPLEMENTATION
|
||||||
|
#undef DQNT_IMPLEMENTATION
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Vec2
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
v2 V2(f32 x, f32 y)
|
||||||
|
{
|
||||||
|
v2 result = {};
|
||||||
|
result.x = x;
|
||||||
|
result.y = y;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 V2i(i32 x, i32 y)
|
||||||
|
{
|
||||||
|
v2 result = V2((f32)x, (f32)y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// String Ops
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
i32 dqnt_strcmp(const char *a, const char *b)
|
||||||
|
{
|
||||||
|
while ((*a) == (*b))
|
||||||
|
{
|
||||||
|
if (!(*a)) return 0;
|
||||||
|
a++;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (((*a) < (*b)) ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b)
|
||||||
|
{
|
||||||
|
while ((*a) == (*b))
|
||||||
|
{
|
||||||
|
if (!(*a)) return 0;
|
||||||
|
a++;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (((*a) < (*b)) ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dqnt_wstrcat(const wchar_t *a, i32 lenA, const wchar_t *b, i32 lenB,
|
||||||
|
wchar_t *out, i32 outLen)
|
||||||
|
{
|
||||||
|
DQNT_ASSERT((lenA + lenB) < outLen);
|
||||||
|
|
||||||
|
i32 outIndex = 0;
|
||||||
|
for (i32 i = 0; i < lenA; i++)
|
||||||
|
out[outIndex++] = a[i];
|
||||||
|
|
||||||
|
for (i32 i = 0; i < lenB; i++)
|
||||||
|
out[outIndex++] = b[i];
|
||||||
|
|
||||||
|
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 result = 0;
|
||||||
|
while ((*a))
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 dqnt_strlen(const char *a)
|
||||||
|
{
|
||||||
|
i32 result = 0;
|
||||||
|
while ((*a))
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PCG (Permuted Congruential Generator) Random Number Generator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public Domain library with thanks to Mattias Gustavsson
|
||||||
|
// https://github.com/mattiasgustavsson/libs/blob/master/docs/rnd.md
|
||||||
|
|
||||||
|
// Convert a randomized u32 value to a float value x in the range 0.0f <= x
|
||||||
|
// < 1.0f. Contributed by Jonatan Hedborg
|
||||||
|
FILE_SCOPE f32 dqnt_rnd_f32_normalized_from_u32_(u32 value)
|
||||||
|
{
|
||||||
|
u32 exponent = 127;
|
||||||
|
u32 mantissa = value >> 9;
|
||||||
|
u32 result = (exponent << 23) | mantissa;
|
||||||
|
f32 fresult = *(f32 *)(&result);
|
||||||
|
return fresult - 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_SCOPE u64 dqnt_rnd_murmur3_avalanche64_(u64 h)
|
||||||
|
{
|
||||||
|
h ^= h >> 33;
|
||||||
|
h *= 0xff51afd7ed558ccd;
|
||||||
|
h ^= h >> 33;
|
||||||
|
h *= 0xc4ceb9fe1a85ec53;
|
||||||
|
h ^= h >> 33;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dqnt_rnd_pcg_seed(RandPCGState *pcg, u32 seed)
|
||||||
|
{
|
||||||
|
u64 value = (((u64)seed) << 1ULL) | 1ULL;
|
||||||
|
value = dqnt_rnd_murmur3_avalanche64_(value);
|
||||||
|
pcg->state[0] = 0U;
|
||||||
|
pcg->state[1] = (value << 1ULL) | 1ULL;
|
||||||
|
dqnt_rnd_pcg_next(pcg);
|
||||||
|
pcg->state[0] += dqnt_rnd_murmur3_avalanche64_(value);
|
||||||
|
dqnt_rnd_pcg_next(pcg);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 dqnt_rnd_pcg_next(RandPCGState *pcg)
|
||||||
|
{
|
||||||
|
u64 oldstate = pcg->state[0];
|
||||||
|
pcg->state[0] = oldstate * 0x5851f42d4c957f2dULL + pcg->state[1];
|
||||||
|
u32 xorshifted = (u32)(((oldstate >> 18ULL) ^ oldstate) >> 27ULL);
|
||||||
|
u32 rot = (u32)(oldstate >> 59ULL);
|
||||||
|
return (xorshifted >> rot) | (xorshifted << ((-(i32)rot) & 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 dqnt_rnd_pcg_nextf(RandPCGState *pcg)
|
||||||
|
{
|
||||||
|
return dqnt_rnd_f32_normalized_from_u32_(dqnt_rnd_pcg_next(pcg));
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 dqnt_rnd_pcg_range(RandPCGState *pcg, i32 min, i32 max)
|
||||||
|
{
|
||||||
|
i32 const range = (max - min) + 1;
|
||||||
|
if (range <= 0) return min;
|
||||||
|
i32 const value = (i32)(dqnt_rnd_pcg_nextf(pcg) * range);
|
||||||
|
return min + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DQNT_IMPLEMENTATION */
|
@ -1,3 +1,5 @@
|
|||||||
#include "win32_dchip8.cpp"
|
#define DQNT_IMPLEMENTATION
|
||||||
|
#include "dqnt.h"
|
||||||
|
|
||||||
|
#include "win32_dchip8.cpp"
|
||||||
#include "dchip8.cpp"
|
#include "dchip8.cpp"
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "dchip8.h"
|
#include "dchip8.h"
|
||||||
#include "dchip8_platform.h"
|
#include "dchip8_platform.h"
|
||||||
|
#include "dqnt.h"
|
||||||
|
|
||||||
FILE_SCOPE bool globalRunning = false;
|
FILE_SCOPE bool globalRunning = false;
|
||||||
FILE_SCOPE LARGE_INTEGER globalQueryPerformanceFrequency;
|
FILE_SCOPE LARGE_INTEGER globalQueryPerformanceFrequency;
|
||||||
@ -209,7 +209,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
renderBitmap.width = header.biWidth;
|
renderBitmap.width = header.biWidth;
|
||||||
renderBitmap.height = header.biHeight;
|
renderBitmap.height = header.biHeight;
|
||||||
renderBitmap.bytesPerPixel = header.biBitCount / 8;
|
renderBitmap.bytesPerPixel = header.biBitCount / 8;
|
||||||
ASSERT(renderBitmap.bytesPerPixel >= 1);
|
DQNT_ASSERT(renderBitmap.bytesPerPixel >= 1);
|
||||||
|
|
||||||
HDC deviceContext = GetDC(mainWindow);
|
HDC deviceContext = GetDC(mainWindow);
|
||||||
renderBitmap.handle =
|
renderBitmap.handle =
|
||||||
@ -230,7 +230,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
u8 stackMemory[4096] = {};
|
u8 stackMemory[4096] = {};
|
||||||
PlatformMemory platformMemory = {};
|
PlatformMemory platformMemory = {};
|
||||||
platformMemory.permanentMem = &stackMemory;
|
platformMemory.permanentMem = &stackMemory;
|
||||||
platformMemory.permanentMemSize = (ARRAY_COUNT(stackMemory) / 4);
|
platformMemory.permanentMemSize = (DQNT_ARRAY_COUNT(stackMemory) / 4);
|
||||||
|
|
||||||
QueryPerformanceFrequency(&globalQueryPerformanceFrequency);
|
QueryPerformanceFrequency(&globalQueryPerformanceFrequency);
|
||||||
const f32 TARGET_FRAMES_PER_S = 60.0f;
|
const f32 TARGET_FRAMES_PER_S = 60.0f;
|
||||||
@ -292,9 +292,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
f32 msPerFrame = 1000.0f * frameTimeInS;
|
f32 msPerFrame = 1000.0f * frameTimeInS;
|
||||||
|
|
||||||
wchar_t windowTitleBuffer[128] = {};
|
wchar_t windowTitleBuffer[128] = {};
|
||||||
_snwprintf_s(windowTitleBuffer, ARRAY_COUNT(windowTitleBuffer),
|
_snwprintf_s(windowTitleBuffer, DQNT_ARRAY_COUNT(windowTitleBuffer),
|
||||||
ARRAY_COUNT(windowTitleBuffer), L"dchip-8 | %5.2f ms/f",
|
DQNT_ARRAY_COUNT(windowTitleBuffer),
|
||||||
msPerFrame);
|
L"dchip-8 | %5.2f ms/f", msPerFrame);
|
||||||
SetWindowText(mainWindow, windowTitleBuffer);
|
SetWindowText(mainWindow, windowTitleBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user