-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWeebCore.c
2843 lines (2448 loc) · 80.5 KB
/
WeebCore.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef WEEBCORE_HEADER
#define WEEBCORE_HEADER
/* opaque handles */
typedef int ImgPtr;
typedef struct _Mesh* Mesh;
typedef struct _Img* Img;
typedef struct _Trans* Trans;
typedef struct _Packer* Packer;
typedef struct _Wnd* Wnd;
typedef struct _Mat* Mat;
typedef struct _Arena* Arena;
typedef struct _Map* Map;
typedef struct _Hash* Hash;
/* ---------------------------------------------------------------------------------------------- */
/* APP INTERFACE */
/* */
/* the app interface is designed to minimize boilerplate when working with weebcore in C. */
/* all you are required to do is define a void AppInit() function where you can bind msg handlers */
/* as you like. */
/* */
/* NOTE: when AppInit is called, nothing is initialized yet. you should do all your init from */
/* On(INIT, MyInitFunc) and only set app parameters in AppInit */
/* ---------------------------------------------------------------------------------------------- */
#ifndef WEEBCORE_LIB
void AppInit();
#endif
/* these funcs can be called in AppInit to set app parameters */
void SetAppName(char* name);
void SetAppClass(char* class);
/* pageSize is the size of a texture page for the texture allocator. there is a tradeoff between
* runtime performance and load times overhead. a big pageSize will result in less texture switches
* during rendering but it will slow down flushing img allocations significantly as it will have
* to update a bigger img on the gpu */
void SetAppPageSize(int pageSize);
/* ---------------------------------------------------------------------------------------------- */
typedef void(* AppHandler)();
/* register handler to be called whenever msg happens. multiple handlers can be bound to same msg.
* handlers are called in the order they are added.
* scroll down to "ENUMS AND CONSTANTS" for a list of msgs, or check out the Examples */
void On(int msg, AppHandler handler);
void RmHandler(int msg, AppHandler handler);
/* time elapsed since the last frame, in seconds */
float Delta();
ImgPtr ImgFromSprFile(char* path);
void PutMesh(Mesh mesh, Mat mat, ImgPtr ptr);
Wnd AppWnd();
ImgPtr ImgAlloc(int width, int height);
void ImgFree(ImgPtr img);
/* discard EVERYTHING allocated on the img allocator. reinitialize built in textures such as the
* default ft. this invalidates all ImgPtr's.
* this is more optimal than freeing each ImgPtr individually if you are going to re-allocate new
* stuff because freeing always leads to fragmentation over time */
void ClrImgs();
/* copy raw pixels dx, dy in the img. anything outside the img size is cropped out.
* note that this replaces pixels. it doesn't do any kind of alpha blending */
void ImgCpyEx(ImgPtr ptr, int* pixs, int width, int height, int dx, int dy);
/* calls ImgCpyEx with dx, dy = 0, 0 */
void ImgCpy(ImgPtr ptr, int* pixs, int width, int height);
/* when you allocate img's they are not immediately sent to the gpu. they will temporarily be blank
* until this is called. the engine calls this automatically every once in a while, but you can
* explicitly call it to force refresh img's.
* this is also automatically called after the INIT msg when using the App interface */
void FlushImgs();
int Argc();
char* Argv(int i);
/* ---------------------------------------------------------------------------------------------- */
/* BUILT-IN MATH FUNCTIONS */
/* ---------------------------------------------------------------------------------------------- */
float Lerp(float a, float b, float amount);
void LerpFlts(int n, float* a, float* b, float* result, float amount);
void MulFltsScalar(int n, float* floats, float* result, float scalar);
void FloorFlts(int n, float* floats, float* result);
void ClampFlts(int n, float* floats, float* result, float min, float max);
void AddFlts(int n, float* a, float* b, float* result);
/* these funcs operate on a rectangle represented as an array of 4 floats (left, top, right, bot) */
void CpyRect(float* dst, float* src);
void SetRect(float* rect, float left, float right, float top, float bot);
void SetRectPos(float* rect, float x, float y);
void SetRectSize(float* rect, float width, float height);
void SetRectLeft(float* rect, float left);
void SetRectRight(float* rect, float right);
void SetRectTop(float* rect, float top);
void SetRectBot(float* rect, float bot);
void NormRect(float* rect); /* swaps values around so width/height aren't negative */
void ClampRect(float* rect, float* other); /* clamp rect to be inside of other rect */
float RectWidth(float* rect);
float RectHeight(float* rect);
float RectX(float* rect);
float RectY(float* rect);
float RectLeft(float* rect);
float RectRight(float* rect);
float RectTop(float* rect);
float RectBot(float* rect);
int PtInRect(float* rect, float x, float y); /* check if xy lies in rect. must be normalized. */
int RectSect(float* a, float* b);
/* check that needle is entirely inside of haystack */
int RectInRect(float* needle, float* haystack);
/* check that needle's area can entirely fit inside of haystack (ignores position) */
int RectInRectArea(float* needle, float* haystack);
/* ---------------------------------------------------------------------------------------------- */
/* OpenGL-like post-multiplied mat. mat memory layout is row major */
Mat MkMat();
void RmMat(Mat mat);
Mat DupMat(Mat source);
/* these return mat for convienience. it's not actually a copy */
Mat SetIdentity(Mat mat);
Mat SetMat(Mat mat, float* matIn);
Mat GetMat(Mat mat, float* matOut);
Mat Scale(Mat mat, float x, float y);
Mat Scale1(Mat mat, float scale);
Mat Pos(Mat mat, float x, float y);
Mat Rot(Mat mat, float deg);
Mat MulMat(Mat mat, Mat other);
Mat MulMatFlt(Mat mat, float* matIn);
/* multiply a b and store the result in a new Mat */
Mat MkMulMat(Mat matA, Mat matB);
Mat MkMulMatFlt(Mat matA, float* matB);
/* trans 2D point in place */
void TransPt(Mat mat, float* point);
/* trans 2D point in place by inverse of mat. note that this only works if the mat is orthogonal */
void InvTransPt(Mat mat, float* point);
/* note: this is a DIRECT pointer to the matrix data so if you modify it it will affect it */
float* MatFlts(Mat mat);
/* ---------------------------------------------------------------------------------------------- */
/* WBSPR FORMAT */
/* this is meant as simple RLE compression for 2D sprites with a limited color palette */
/* ---------------------------------------------------------------------------------------------- */
typedef struct _Spr* Spr;
Spr MkSpr(char* data, int length);
Spr MkSprFromArr(char* data);
Spr MkSprFromFile(char* filePath);
void RmSpr(Spr spr);
int SprWidth(Spr spr);
int SprHeight(Spr spr);
void SprToArgb(Spr spr, int* argb);
int* SprToArgbArr(Spr spr);
/* returns a resizable array that must be freed with RmArr */
char* ArgbToSprArr(int* argb, int width, int height);
/* Format Details:
*
* char[4] "SP"
* varint formatVersion
* varint width, height
* varint paletteLength
* int32 palette[paletteLength]
* Blob {
* varint type (repeat/data)
* varint size
* varint paletteIndices[size] <- 1 varint for repeat
* }
* ...
*
* varint's are protobuf style encoded integers. see EncVarI32 */
/* ---------------------------------------------------------------------------------------------- */
/* RENDER UTILS */
/* ---------------------------------------------------------------------------------------------- */
/* calls PutMeshRawEx with zero u/v offset */
void PutMeshRaw(Mesh mesh, Mat mat, Img img);
/* create a mat from scale, position, origin, rot applied in a fixed order */
Trans MkTrans();
void RmTrans(Trans trans);
void ClrTrans(Trans trans);
/* these return trans for convenience. it's not actually a copy */
Trans SetScale(Trans trans, float x, float y);
Trans SetScale1(Trans trans, float scale);
Trans SetPos(Trans trans, float x, float y);
Trans SetOrig(Trans trans, float x, float y);
Trans SetRot(Trans trans, float deg);
Mat ToMat(Trans trans);
/* the ortho version of To* functions produce a mat that is orthogonal (doesn't apply scale
* among other things) this is useful for trivial inversion */
Mat ToMatOrtho(Trans trans);
/* the mat returned by this does not need to be destroyed. it will be automatically destroyed
* when RmTrans is called.
*
* note that subsequent calls to this function will invalidate the previously generated mat
*
* Ortho version does not share the same mat as the non-Ortho so it doesnt invalidate it
*
* it's recommended to not hold onto these Mat pointers either way. if the Trans doesn't change,
* the Mat will not be recalculated, so it's cheap to call these everywhere */
Mat ToTmpMat(Trans trans);
Mat ToTmpMatOrtho(Trans trans);
/* add a rectangle to mesh */
void Quad(Mesh mesh, float x, float y, float width, float height);
/* add a textured rectangle to mesh. note that the u/v coordinates are in pixels, since we usually
* want to work pixel-perfect in 2d */
void ImgQuad(Mesh mesh,
float x, float y, float u, float v,
float width, float height, float uWidth, float vHeight
);
/* add a triangle to mesh */
void Tri(Mesh mesh, float x1, float y1, float x2, float y2, float x3, float y3);
void ImgTri(Mesh mesh,
float x1, float y1, float u1, float v1,
float x2, float y2, float u2, float v2,
float x3, float y3, float u3, float v3
);
/* draw gradients using vertex color interpolation */
void QuadGradH(Mesh mesh, float x, float y, float width, float height, int n, int* colors);
void QuadGradV(Mesh mesh, float x, float y, float width, float height, int n, int* colors);
/* convert Argb color to { r, g, b, a } (0.0-1.0) */
void ColToFlts(int color, float* floats);
/* convert { r, g, b, a } (0.0-1.0) to Argb color */
int FltsToCol(float* f);
/* linearly interpolate between colors a and b */
int Mix(int a, int b, float amount);
/* multiply color's rgb values by scalar (does not touch alpha) */
int MulScalar(int color, float scalar);
/* add colors together (clamps values to avoid overflow) */
int Add(int a, int b);
/* alpha blend between color src and dst. alpha is not premultiplied */
int AlphaBlend(int src, int dst);
/* same as alpha blend but blends in place into dst */
void AlphaBlendp(int* dst, int src);
/* convert rgba pixs to 1bpp. all non-transparent colors become a 1 and transparency becomes 0.
* the data is tightly packed (8 pixs per byte).
* the returned data is an array and must be freed with ArrFree */
char* ArgbToOneBpp(int* pixs, int numPixs);
char* ArgbArrToOneBpp(int* pixs);
int* OneBppToArgb(char* data, int numBytes);
int* OneBppArrToArgb(char* data);
/* ---------------------------------------------------------------------------------------------- */
/* BITMAP FONTS */
/* ---------------------------------------------------------------------------------------------- */
typedef struct _Ft* Ft;
/* simplest form of bitmap ft.
*
* this assumes pixs is a tightly packed grid of 32x3 characters that cover ascii 0x20-0x7f
* (from space to the end of the ascii table).
*
* while this is the fastest way for the renderer to look up characters, it should only be used in
* cases where you have a hardcoded ft that's never gonna change. it was created to bootstrap
* the built-in ft */
Ft MkFtFromSimpleGrid(int* pixs, int width, int height, int charWidth, int charHeight);
Ft MkFtFromSimpleGridFile(char* filePath, int charWidth, int charHeight);
/* basic built in bitmap ft */
Ft DefFt();
void RmFt(Ft ft);
ImgPtr FtImg(Ft ft);
/* generate vertices and uv's for drawing string. must be rendered with the ft img from
* FtImg or a img that has the same exact layout */
void FtMesh(Mesh mesh, Ft ft, int x, int y, char* string);
void PutFt(Ft ft, int col, int x, int y, char* string);
/* ---------------------------------------------------------------------------------------------- */
/* RESIZABLE ARRAYS */
/* */
/* make sure your initial pointer is initialized to NULL which counts as an empty array. */
/* these are special fat pointers and must be freed with RmArr */
/* ---------------------------------------------------------------------------------------------- */
void RmArr(void* array);
int ArrLen(void* array);
int ArrCap(void* array);
void SetArrLen(void* array, int len);
/* compare the raw memory of a and b using MemCmp */
int ArrMemCmp(void* a, void* b);
/* join array of strs into one str where every element is separated by separator */
char* ArrStrJoin(char** array, char* separator);
#define ArrDup(arr) ArrDupEx(arr, sizeof(arr[0]))
/* shorthand macro to append a single element to the array */
#define ArrCat(pArr, x) { \
ArrReserve((pArr), 1); \
(*(pArr))[ArrLen(*(pArr))] = (x); \
SetArrLen(*(pArr), ArrLen(*(pArr)) + 1); \
}
/* reserve memory for at least numElements extra elements.
* returns a pointer to the end of the array */
#define ArrReserve(pArr, numElements) \
ArrReserveEx((void**)(pArr), sizeof((*pArr)[0]), numElements)
/* reserve memory for at least numElements extra elements and set the
* array length to current length + numElements.
* returns a pointer to the beginning of the new elements */
#define ArrAlloc(pArr, numElements) \
ArrAllocEx((void**)(pArr), sizeof((*pArr)[0]), numElements)
void ArrStrCat(char** pArr, char* str);
void* ArrReserveEx(void** pArr, int elementSize, int numElements);
void* ArrAllocEx(void** pArr, int elementSize, int numElements);
void* ArrDupEx(void* array, int elementSize);
/* ---------------------------------------------------------------------------------------------- */
/* ARENA */
/* */
/* simple allocator that pre-allocs chunks of memory for a more contiguous allocation but isn't */
/* as expensive as resizing an Arr because it doesn't realloc */
/* ---------------------------------------------------------------------------------------------- */
Arena MkArena();
Arena MkArenaEx(int chunkSize);
void RmArena(Arena arena);
/* if n is bigger than the chunk size, a new chunk at least as big as n will be allocated */
void* ArenaAlloc(Arena arena, int n);
void* ArenaMemDup(Arena arena, void* p, int n);
/* ---------------------------------------------------------------------------------------------- */
/* MAP */
/* */
/* sparse array that maps integers to values */
/* ---------------------------------------------------------------------------------------------- */
Map MkMap();
void RmMap(Map map);
void MapSet(Map map, int key, void* val);
void* MapGet(Map map, int key);
/* return the number of collisions (keys that hashed to the same value). this is mostly used for
* debugging and checking whether the map is operating as intended */
int MapColls(Map map);
/* these functions can be used to iterate keys */
int MapNumKeys(Map map);
int MapKey(Map map, int i);
/* ---------------------------------------------------------------------------------------------- */
/* HASH */
/* */
/* sparse array that maps strings to values */
/* ---------------------------------------------------------------------------------------------- */
Hash MkHash();
void RmHash(Hash hash);
/* note that Hash manages its own internal copies of the key, there's no need to keep it around */
void HashSet(Hash hash, char* key, void* val);
void HashSetb(Hash hash, void* keyData, int keySize, void* val);
void* HashGet(Hash hash, char* key);
void* HashGetb(Hash hash, char* keyData, int keySize);
int HashHas(Hash hash, char* key);
int HashHasb(Hash hash, char* keyData, int keySize);
int HashColls(Hash map); /* see MapColls */
/* these functions can be used to iterate keys */
int HashNumKeys(Hash hash);
void* HashKey(Hash hash, int i);
int HashKeyLen(Hash hash, int i);
/* ---------------------------------------------------------------------------------------------- */
/* RECT PACKER */
/* */
/* attempts to efficiently pack rectangles inside a bigger rectangle. internally used to */
/* automatically stitch together all the imags and not have the renderer swap img every time. */
/* ---------------------------------------------------------------------------------------------- */
Packer MkPacker(int width, int height);
void RmPacker(Packer pak);
/* rect is an array of 4 floats (left, right, top, bottom) like in the Rect funcs
*
* NOTE: this adjusts rect in place and just returns it for convenience. make a copy if you don't
* want to lose rect's original values.
*
* returns NULL if rect doesn't fit */
float* Pack(Packer pak, float* rect);
/* mark rect as a free area. this can be used to remove already packed rects */
void PackFree(Packer pak, float* rect);
/* ---------------------------------------------------------------------------------------------- */
/* MISC UTILS AND MACROS */
/* ---------------------------------------------------------------------------------------------- */
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Clamp(x, min, max) Max(min, Min(max, x))
/* (a3, b3) = (a1, b1) - (a2, b2) */
#define Sub2(a1, b1, a2, b2, a3, b3) \
((a3) = (a1) - (a2)), \
((b3) = (b1) - (b2))
/* cross product between (x1, y1) and (x2, y2) */
#define Cross(x1, y1, x2, y2) ((x1) * (y2) - (y1) * (x2))
#define ToRad(deg) ((deg) / 360 * PI * 2)
/* return the closest power of two that is higher than x */
int RoundUpToPowerOfTwo(int x);
/* return the closest multiple of a that is lower than value. a must be a power of 2 */
int AlignDownToPowerOfTwo(int x, int a);
/* return the closest multiple of a that is higher than value. a must be a power of 2 */
int AlignUpToPowerOfTwo(int x, int a);
/* null-terminated string utils */
int StrLen(char* s);
void StrCpy(char* dst, char* src);
int StrCmp(char* a, char* b);
/* mem utils */
int MemCmp(void* a, void* b, int n);
void* MemDup(void* p, int n);
/* protobuf style varints. encoded in base 128. each byte contains 7 bits of the integer and the
* msb is set if there's more. byte order is little endian */
int DecVarI32(char** pData); /* increments *pData past the varint */
int EncVarI32(void* data, int x); /* returns num of bytes written */
void CatVarI32(char** pArr, int x); /* append to resizable arr */
/* encode integers in little endian */
int EncI32(void* data, int x);
int DecI32(char** pData);
void CatI32(char** pArr, int x);
void SwpFlts(float* a, float* b);
void SwpPtrs(void** a, void** b);
/* encode data to a b64 string. returned string must be freed with Free */
char* ToB64(void* data, int dataSize);
char* ArrToB64(char* data);
char* ArrFromB64(char* b64Data);
int HashStr(void* data, int len);
int HashI32(int x);
/* converts x to a string with the specified base and appends the characters to arr.
base is clamped to 1-16 */
void ArrStrCatI32(char** arr, int x, int base);
/* like ArrStrCatI32 but creates an arr on the fly and null terminates it. must be rmd with RmArr */
char* I32ToArrStr(int x, int base);
typedef int QsortCmp(void*, void*);
void Qsort(void** arr, int len, QsortCmp* cmp);
void QsortStrs(char** strarr, int len);
/* ---------------------------------------------------------------------------------------------- */
/* ENUMS AND CONSTANTS */
/* ---------------------------------------------------------------------------------------------- */
#ifndef PI
#define PI 3.141592653589793238462643383279502884
#endif
/* message types returned by MsgType */
enum {
QUIT_REQUEST = 1,
KEYDOWN,
KEYUP,
MOTION,
SIZE,
INIT,
FRAME,
QUIT,
LAST_MSG_TYPE
};
/* flags for the bitfield returned by MsgKeyState */
enum {
FSHIFT = 1<<1,
FCONTROL = 1<<2,
FALT = 1<<3,
FSUPER = 1<<4,
FCAPS_LOCK = 1<<5,
FNUM_LOCK = 1<<6,
FREPEAT = 1<<7,
FLAST_STATE
};
#define FCTRL FCONTROL
#define MLEFT MOUSE1
#define MMID MOUSE2
#define MRIGHT MOUSE3
#define MWHEELUP MOUSE4
#define MWHEELDOWN MOUSE5
/* keys returned by MsgKey */
enum {
MOUSE1 = 1,
MOUSE2 = 2,
MOUSE3 = 3,
MOUSE4 = 4,
MOUSE5 = 5,
SPACE = 32,
APOSTROPHE = 39,
COMMA = 44,
MINUS = 45,
PERIOD = 46,
SLASH = 47,
K0 = 48,
K1 = 49,
K2 = 50,
K3 = 51,
K4 = 52,
K5 = 53,
K6 = 54,
K7 = 55,
K8 = 56,
K9 = 57,
SEMICOLON = 59,
EQUAL = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LEFT_BRACKET = 91,
BACKSLASH = 92,
RIGHT_BRACKET = 93,
GRAVE_ACCENT = 96,
WORLD_1 = 161,
WORLD_2 = 162,
ESCAPE = 256,
ENTER = 257,
TAB = 258,
BACKSPACE = 259,
INSERT = 260,
DELETE = 261,
RIGHT = 262,
LEFT = 263,
DOWN = 264,
UP = 265,
PAGE_UP = 266,
PAGE_DOWN = 267,
HOME = 268,
END = 269,
CAPS_LOCK = 280,
SCROLL_LOCK = 281,
NUM_LOCK = 282,
PRINT_SCREEN = 283,
PAUSE = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
F13 = 302,
F14 = 303,
F15 = 304,
F16 = 305,
F17 = 306,
F18 = 307,
F19 = 308,
F20 = 309,
F21 = 310,
F22 = 311,
F23 = 312,
F24 = 313,
F25 = 314,
KP_0 = 320,
KP_1 = 321,
KP_2 = 322,
KP_3 = 323,
KP_4 = 324,
KP_5 = 325,
KP_6 = 326,
KP_7 = 327,
KP_8 = 328,
KP_9 = 329,
KP_DECIMAL = 330,
KP_DIVIDE = 331,
KP_MULTIPLY = 332,
KP_SUBTRACT = 333,
KP_ADD = 334,
KP_ENTER = 335,
KP_EQUAL = 336,
LEFT_SHIFT = 340,
LEFT_CONTROL = 341,
LEFT_ALT = 342,
LEFT_SUPER = 343,
RIGHT_SHIFT = 344,
RIGHT_CONTROL = 345,
RIGHT_ALT = 346,
RIGHT_SUPER = 347,
MENU = 348,
LAST_KEY
};
/* img wrap modes */
enum {
CLAMP_TO_EDGE,
MIRRORED_REPEAT,
REPEAT,
LAST_IMG_WRAP
};
/* img filters */
enum {
NEAREST,
LINEAR,
LAST_IMG_FILTER
};
/* ---------------------------------------------------------------------------------------------- */
/* MISC DEBUG AND SEMI-INTERNAL INTERFACES */
/* ---------------------------------------------------------------------------------------------- */
/* these could be used to use the app interface from FFI (minus the handlers system unless your ffi
* has simple ways to pass callbacks to C). see implementation of AppMain to see how you would do
* it from FFI */
/* call the built in app handlers for the current msg */
int AppHandleMsg();
/* call the built in app handlers for the FRAME msg. this should be called at the start of every
* tick of the game loop. note that this not call SwpBufs, you have to call it yourself */
void AppFrame();
/* true if no QUIT_REQUEST msg has been received */
int AppRunning();
/* (automatically called by AppMain) initialize the app globals. */
void MkApp(int argc, char* argv[]);
/* (automatically called by AppMain)
* clean up the app globals (optional, as virtual memory cleans everything up when we exit) */
void RmApp();
/* (automatically called by the platform layer)
* initializes app and runs the main loop.
* this also takes care of calling pseudo msgs like INIT, FRAME and calling SwpBufs */
int AppMain(int argc, char* argv[]);
/* enable debug ui for the img allocator */
void DiagImgAlloc(int enabled);
/* ---------------------------------------------------------------------------------------------- */
/* PLATFORM LAYER */
/* */
/* you can either include Platform/Platform.h to use the built in sample platform layers or write */
/* your own by defining these structs and funcs */
/* ---------------------------------------------------------------------------------------------- */
Wnd MkWnd(char* name, char* class);
void RmWnd(Wnd wnd);
void SetWndName(Wnd wnd, char* wndName);
void SetWndClass(Wnd wnd, char* className);
void SetWndSize(Wnd wnd, int width, int height);
int WndWidth(Wnd wnd);
int WndHeight(Wnd wnd);
/* get time elapsed in seconds since the last SwpBufs. guaranteed to return non-zero even if
* no SwpBufs happened */
float WndDelta(Wnd wnd);
/* FPS limiter, 0 for unlimited. limiting happens in SwpBufs. note that unlimited fps still
* waits for the minimum timer resolution for GetTime */
void SetWndFPS(Wnd wnd, int fps);
/* fetch one message. returns non-zero as long as there are more */
int NextMsg(Wnd wnd);
/* sends QUIT_REQUEST message to the wnd */
void PostQuitMsg(Wnd wnd);
/* these funcs get data from the last message fetched by NextMsg */
int MsgType(Wnd wnd);
int Key(Wnd wnd);
int KeyState(Wnd wnd);
int MouseX(Wnd wnd);
int MouseY(Wnd wnd);
int MouseDX(Wnd wnd);
int MouseDY(Wnd wnd);
/* allocates n bytes and initializes memory to zero */
void* Alloc(int n);
/* reallocate p to new size n. memory that wasn't initialized is not guaranteed to be zero */
void* Realloc(void* p, int n);
void Free(void* p);
void MemSet(void* p, unsigned char val, int n);
void MemCpy(void* dst, void* src, int n);
/* same as MemCpy but allows overlapping regions of memory */
void MemMv(void* dst, void* src, int n);
/* write data to disk. returns number of bytes written or < 0 for errors */
int WrFile(char* path, void* data, int dataLen);
/* read up to maxSize bytes from disk */
int RdFile(char* path, void* data, int maxSize);
/* ---------------------------------------------------------------------------------------------- */
/* MATH FUNCTIONS */
/* */
/* you can either include Platform/Platform.h to use the built in sample implementations or write */
/* your own by defining these funcs */
/* ---------------------------------------------------------------------------------------------- */
float FltMod(float x, float y); /* returns x modulo y */
float Sin(float deg);
float Cos(float deg);
int Ceil(float x);
int Floor(float x);
float Sqrt(float x);
/* ---------------------------------------------------------------------------------------------- */
/* RENDERER */
/* */
/* you can either include Platform/Platform.h to use the built in sample renderers or write your */
/* own by defining these structs and funcs */
/* ---------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------- */
/* Mesh is a collection of vertices that will be rendered using the same img and trans. try
* to batch up as much stuff into a mesh as possible for optimal performance. */
Mesh MkMesh();
void RmMesh(Mesh mesh);
/* change current color. color is Argb 32-bit int (0xAARRGGBB). 255 alpha = completely transparent,
* 0 alpha = completely opaque. the default color for a mesh should be 0xffffff */
void Col(Mesh mesh, int color);
/* these are for custom meshes.
* wrap Vert and Face calls between Begin and End.
* indices start at zero and we are indexing the vertices submitted between Begin and End. see the
* implementations of Quad and Tri for examples */
void Begin(Mesh mesh);
void End(Mesh mesh);
void Vert(Mesh mesh, float x, float y);
void ImgCoord(Mesh mesh, float u, float v);
void Face(Mesh mesh, int i1, int i2, int i3);
/* this is internally used to do img atlases and map relative uv's to the bigger image */
void PutMeshRawEx(Mesh mesh, Mat mat, Img img, float uOffs, float vOffs);
/* ---------------------------------------------------------------------------------------------- */
Img MkImg();
void RmImg(Img img);
/* set wrap mode for img coordinates. default is REPEAT */
void SetImgWrapU(Img img, int mode);
void SetImgWrapV(Img img, int mode);
/* set min/mag filter for img. default is NEAREST */
void SetImgMinFilter(Img img, int filter);
void SetImgMagFilter(Img img, int filter);
/* set the img's pix data. must be an array of 0xAARRGGBB colors as explained in Col.
* pixs are laid out row major - for example a 4x4 image would be:
* { px00, px10, px01, px11 }
* note that this is usually an expensive call. only update the img data when it's actually
* changing.
* return img for convenience */
Img Pixs(Img img, int width, int height, int* data);
/* same as Pixs but you can specify stride which is how many bytes are between the beginning
* of each row, for cases when you have extra padding or when you're submitting a sub-region of a
* bigger image */
Img PixsEx(Img img, int width, int height, int* data, int stride);
/* ---------------------------------------------------------------------------------------------- */
/* flush all rendered geometry to the screen */
void SwpBufs(Wnd wnd);
/* set rendering rectangle from the top left of the wnd, in pixs. this is automatically called
* when the wnd is resized. it can also be called manually to render to a subregion of the
* wnd. all coordinates passed to other rendering functions start from the top left corner of
* this rectangle. */
void Viewport(Wnd wnd, int x, int y, int width, int height);
/* the initial color of a blank frame */
void ClsCol(int color);
#endif /* WEEBCORE_HEADER */
/* ############################################################################################## */
/* ############################################################################################## */
/* ############################################################################################## */
/* */
/* Hdr part ends here. This is all you need to know to use it. Implementation below. */
/* */
/* ############################################################################################## */
/* ############################################################################################## */
/* ############################################################################################## */
#if defined(WEEBCORE_IMPLEMENTATION) && !defined(WEEBCORE_OVERRIDE_MONOLITHIC_BUILD)
/* ---------------------------------------------------------------------------------------------- */
/* to minimize duplication, I decided to have common flags shared by all internal stuff */
#define DIRTY (1<<0)
#define ORTHO_DIRTY (1<<1)
#define RUNNING (1<<2)
/* ---------------------------------------------------------------------------------------------- */
typedef struct _ArrHdr {
int capacity;
int length;
} ArrHdr;
static ArrHdr* GetArrHdr(void* array) {
if (!array) return 0;
return (ArrHdr*)array - 1;
}
void RmArr(void* array) {
Free(GetArrHdr(array));
}
int ArrLen(void* array) {
if (!array) return 0;
return GetArrHdr(array)->length;
}
int ArrCap(void* array) {
if (!array) return 0;
return GetArrHdr(array)->capacity;
}
void SetArrLen(void* array, int length) {
if (array) {
GetArrHdr(array)->length = length;
}
}
int ArrMemCmp(void* a, void* b) {
int alen = ArrLen(a);
int blen = ArrLen(b);
if (alen > blen) {
return 1;
} else if (alen < blen) {
return -1;
}
return MemCmp(a, b, alen);
}
void ArrStrCat(char** pArr, char* str) {
for (; *str; ++str) {
ArrCat(pArr, *str);
}
}
void* ArrReserveEx(void** pArr, int elementSize, int numElements) {
ArrHdr* header;
if (!*pArr) {
int capacity = RoundUpToPowerOfTwo(Max(numElements, 16));
header = Alloc(sizeof(ArrHdr) + elementSize * capacity);
header->capacity = capacity;
*pArr = header + 1;
} else {
int minCapacity;
header = GetArrHdr(*pArr);
minCapacity = header->length + numElements;
if (header->capacity < minCapacity) {
int newSize;
while (header->capacity < minCapacity) {
header->capacity *= 2;
}
newSize = sizeof(ArrHdr) + elementSize * header->capacity;
header = Realloc(header, newSize);
*pArr = header + 1;
}
}
return (char*)*pArr + ArrLen(*pArr) * elementSize;
}
void* ArrAllocEx(void** pArr, int elementSize, int numElements) {
void* res = ArrReserveEx(pArr, elementSize, numElements);
SetArrLen(*pArr, ArrLen(*pArr) + numElements);
return res;
}
void* ArrDupEx(void* array, int elementSize) {
void* res = 0;
ArrAllocEx(&res, elementSize, ArrLen(array));
if (res) {
MemCpy(res, array, ArrLen(array) * elementSize);
}
return res;
}
char* ArrStrJoin(char** array, char* separator) {
int i;
char* res = 0;
for (i = 0; i < ArrLen(array); ++i) {
ArrStrCat(&res, array[i]);
ArrStrCat(&res, separator);
}
ArrCat(&res, 0);
return res;
}
/* ---------------------------------------------------------------------------------------------- */
struct _Arena {
char** chunks;
char* p;
int freeBytes;
int minChunkSize;
};
Arena MkArena() { return MkArenaEx(1024); }
Arena MkArenaEx(int chunkSize) {
Arena arena = Alloc(sizeof(struct _Arena));
if (arena) {
arena->minChunkSize = chunkSize;
}