hj
kj
This commit is contained in:
parent
2b15552401
commit
62b37ed348
|
@ -58,7 +58,9 @@
|
|||
"typeinfo": "cpp",
|
||||
"execution": "cpp",
|
||||
"stdbool.h": "c",
|
||||
"fumoengine.h": "c"
|
||||
"fumoengine.h": "c",
|
||||
"event.h": "c",
|
||||
"fumocommon.h": "c"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
#include <iso646.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define nullptr ((void *)0)
|
||||
|
|
|
@ -2,32 +2,62 @@
|
|||
#include "platform.h"
|
||||
|
||||
|
||||
VectorT FUMOSYS_VEC_T = VECTOR_T(struct FumoHook);
|
||||
|
||||
|
||||
void Panic(char *message)
|
||||
{
|
||||
printf(message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void InvokeUpdate(void_func func, void *arg)
|
||||
{
|
||||
struct { nsec frametime; } *args = arg;
|
||||
|
||||
((update_func)func)(args->frametime);
|
||||
}
|
||||
|
||||
bool FumoInit(struct FumoGame *game)
|
||||
bool CreateFumoInstance(struct FumoInstance *instance)
|
||||
{
|
||||
if (!PlatformInit())
|
||||
Panic("Platform failed to initialize");
|
||||
|
||||
if (!CreateController(&game->ctrl))
|
||||
if (!CreateController(&instance->ctrl))
|
||||
Panic("Out of memory");
|
||||
|
||||
if (!CreateEvent(&game->update))
|
||||
Panic("Out of memory");
|
||||
|
||||
if (!BeginInputThread(&game->input_hand))
|
||||
if (!CreateInputThread(&instance->input_hand))
|
||||
Panic("Input handle failed to initialize");
|
||||
|
||||
return 0;
|
||||
if (!CreateTerminal(&instance->term, 20, 10))
|
||||
Panic("Out of memory");
|
||||
|
||||
if (!CreateEvent(&instance->on_start))
|
||||
Panic("Out of memory");
|
||||
|
||||
if (!CreateEvent(FUMOSYS_VEC_T, &instance->on_update))
|
||||
Panic("Out of memory");
|
||||
|
||||
instance->time = TimeNow();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FumoInstanceRun(struct FumoInstance *instance)
|
||||
{
|
||||
usize buf_n = TerminalMaxOut(&instance->term);
|
||||
char *buf = malloc(buf_n);
|
||||
|
||||
while (true) {
|
||||
if (!InputAquire(&instance->input_hand))
|
||||
Panic("Aquire failed");
|
||||
|
||||
ControllerPoll(&instance->ctrl, &instance->input_hand.recs);
|
||||
|
||||
if (!InputRelease(&instance->input_hand))
|
||||
Panic("Release failed");
|
||||
|
||||
nsec now = TimeNow();
|
||||
instance->frametime = now - instance->time;
|
||||
FumoInvoke(instance, &instance->on_update);
|
||||
instance->time = now;
|
||||
|
||||
TerminalPrint(&instance->term, buf, buf_n);
|
||||
puts(buf);
|
||||
|
||||
_sleep(100);
|
||||
}
|
||||
}
|
|
@ -3,21 +3,27 @@
|
|||
#include "event.h"
|
||||
#include "fumocommon.h"
|
||||
#include "input.h"
|
||||
#include "terminal.h"
|
||||
#include "vector.h"
|
||||
|
||||
|
||||
struct FumoGame {
|
||||
struct FumoInstance {
|
||||
struct Controller ctrl;
|
||||
struct InputHandle input_hand;
|
||||
struct Terminal term;
|
||||
|
||||
struct Event start;
|
||||
struct Event draw;
|
||||
struct Event update;
|
||||
struct Event on_start;
|
||||
struct Event on_update;
|
||||
|
||||
nsec time;
|
||||
nsec frametime;
|
||||
};
|
||||
|
||||
|
||||
void Panic(char *message);
|
||||
|
||||
bool FumoInit(struct FumoGame *game);
|
||||
bool CreateFumoInstance(struct FumoInstance *game);
|
||||
|
||||
bool FumoInstanceHook(struct Vector *vec, update_func update, void *state);
|
||||
|
||||
bool FumoInstanceRun(struct FumoInstance *game);
|
|
@ -1,19 +1,17 @@
|
|||
#include "event.h"
|
||||
|
||||
#define INIT_CAPACITY 16
|
||||
|
||||
|
||||
bool CreateEvent(struct Event *event)
|
||||
{
|
||||
void_func *callbacks = malloc(INIT_CAPACITY * sizeof(void_func));
|
||||
struct Method *methods = malloc(16 * sizeof(struct Method));
|
||||
|
||||
if (callbacks == nullptr)
|
||||
if (methods == nullptr)
|
||||
return false;
|
||||
|
||||
*event = (struct Event) {
|
||||
.callbacks = callbacks,
|
||||
.methods = methods,
|
||||
.len = 0,
|
||||
.capacity = INIT_CAPACITY
|
||||
.capacity = 16
|
||||
};
|
||||
|
||||
return true;
|
||||
|
@ -21,30 +19,34 @@ bool CreateEvent(struct Event *event)
|
|||
|
||||
void FreeEvent(struct Event *event)
|
||||
{
|
||||
free(event->callbacks);
|
||||
free(event->methods);
|
||||
}
|
||||
|
||||
bool EventRegister(struct Event *event, void_func callback)
|
||||
bool EventRegister(struct Event *event, callback func, void *instance)
|
||||
{
|
||||
if (event->len == event->capacity) {
|
||||
usize new_size = event->capacity * 2 * sizeof(void_func);
|
||||
void_func *new_callbacks = realloc(event->callbacks, new_size);
|
||||
usize new_size = event->capacity * 2 * sizeof(struct Method);
|
||||
struct Method *new_methods = realloc(event->methods, new_size);
|
||||
|
||||
if (new_callbacks == nullptr)
|
||||
if (new_methods == nullptr)
|
||||
return false;
|
||||
|
||||
event->callbacks = new_callbacks;
|
||||
event->methods = new_methods;
|
||||
event->capacity = new_size;
|
||||
}
|
||||
|
||||
event->callbacks[event->len++] = callback;
|
||||
event->methods[event->len++] = (struct Method) {
|
||||
.func = func,
|
||||
.instance = instance
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventInvoke(struct Event *event, void *args)
|
||||
void EventInvoke(struct Event *event, void *state)
|
||||
{
|
||||
for (usize i = 0; i < event->len; i++) {
|
||||
event->callbacks[i](args);
|
||||
struct Method *method = event->methods + i;
|
||||
method->func(state, method->instance);
|
||||
}
|
||||
}
|
|
@ -1,27 +1,26 @@
|
|||
#pragma once
|
||||
#include <iso646.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fumocommon.h"
|
||||
|
||||
|
||||
typedef void (*void_func)(void *arg);
|
||||
|
||||
typedef void (*invoker_func)(void_func func, void *arg);
|
||||
typedef void (*callback)(void *state, void *instance);
|
||||
|
||||
struct Method {
|
||||
callback func;
|
||||
void *instance;
|
||||
};
|
||||
|
||||
struct Event {
|
||||
void_func *callbacks;
|
||||
struct Method *methods;
|
||||
usize len;
|
||||
usize capacity;
|
||||
};
|
||||
|
||||
|
||||
bool CreateEvent(struct Event *event);
|
||||
bool CreateEvent(struct Event *event, void *state);
|
||||
|
||||
bool EventRegister(struct Event *event, void_func callback);
|
||||
bool EventRegister(struct Event *event, callback func, void *instance);
|
||||
|
||||
void EventInvoke(struct Event *event, void *args);
|
||||
void EventInvoke(struct Event *event);
|
|
@ -3,26 +3,26 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
void *get_ptr(RingBufferT T, struct RingBufferHead *head, size_t i)
|
||||
void *get_ptr(RingBufferT T, struct RingBufferHead *head, usize i)
|
||||
{
|
||||
u8 *bytes = (u8 *)head;
|
||||
return bytes + T->OFFSET + T->SIZE * i;
|
||||
}
|
||||
|
||||
size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head)
|
||||
usize RingBufferEmpty(RingBufferT T, struct RingBufferHead *head)
|
||||
{
|
||||
return T->LEN - head->len;
|
||||
}
|
||||
|
||||
void *RingBufferGet(RingBufferT T, struct RingBufferHead *head, size_t i)
|
||||
void *RingBufferGet(RingBufferT T, struct RingBufferHead *head, usize i)
|
||||
{
|
||||
size_t wrap_i = (head->start + i) % T->LEN;
|
||||
usize wrap_i = (head->start + i) % T->LEN;
|
||||
return get_ptr(T, head, wrap_i);
|
||||
}
|
||||
|
||||
void *RingBufferNext(RingBufferT T, struct RingBufferHead *head)
|
||||
{
|
||||
size_t wrap_i = (head->start + head->len) % T->LEN;
|
||||
usize wrap_i = (head->start + head->len) % T->LEN;
|
||||
return get_ptr(T, head, wrap_i);
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ void RingBufferTransfer(
|
|||
struct RingBufferHead *dest,
|
||||
struct RingBufferHead *tmp
|
||||
) {
|
||||
size_t copy_max = min_usize(T->LEN - dest->len, tmp->len);
|
||||
usize copy_max = min_usize(T->LEN - dest->len, tmp->len);
|
||||
|
||||
for (size_t i = 0; i < copy_max; i++) {
|
||||
for (usize i = 0; i < copy_max; i++) {
|
||||
void *to = RingBufferGet(T, dest, dest->len + i);
|
||||
void *from = RingBufferGet(T, tmp, i);
|
||||
memcpy(to, from, T->SIZE);
|
||||
|
@ -49,15 +49,15 @@ void RingBufferTransfer(
|
|||
tmp->len -= copy_max;
|
||||
}
|
||||
|
||||
size_t RingBufferOut(
|
||||
usize RingBufferOut(
|
||||
RingBufferT T,
|
||||
size_t n,
|
||||
usize n,
|
||||
void *dest,
|
||||
struct RingBufferHead *src
|
||||
) {
|
||||
size_t copy_max = min_usize(n, src->len);
|
||||
usize copy_max = min_usize(n, src->len);
|
||||
|
||||
for (size_t i = 0; i < copy_max; i++) {
|
||||
for (usize i = 0; i < copy_max; i++) {
|
||||
void *to = (u8 *)dest + i * T->SIZE;
|
||||
void *from = RingBufferGet(T, src, i);
|
||||
memcpy(to, from, T->SIZE);
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
#pragma once
|
||||
#include <iso646.h>
|
||||
#include <stdalign.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fumocommon.h"
|
||||
|
||||
|
||||
typedef const struct RingBufferT {
|
||||
size_t OFFSET;
|
||||
size_t SIZE;
|
||||
size_t LEN;
|
||||
} *const RingBufferT;
|
||||
|
||||
struct RingBufferHead {
|
||||
size_t len;
|
||||
size_t start;
|
||||
};
|
||||
|
||||
#define RINGBUF_T_INIT(RBUF_STRUCT, RBUF_ITEM, RBUF_LEN) \
|
||||
#define RINGBUF_T(RBUF_ITEM_T, RBUF_LEN) \
|
||||
(&(struct RingBufferT) { \
|
||||
.OFFSET = offsetof(struct { \
|
||||
struct RingBufferHead head; \
|
||||
RBUF_ITEM item; \
|
||||
RBUF_ITEM_T item; \
|
||||
}, item), \
|
||||
.SIZE = sizeof(RBUF_ITEM), \
|
||||
.SIZE = sizeof(RBUF_ITEM_T), \
|
||||
.LEN = RBUF_LEN \
|
||||
}) \
|
||||
|
||||
#define RINGBUF_HEAD_INIT ((struct RingBufferHead) { 0, 0 })
|
||||
|
||||
size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head);
|
||||
|
||||
typedef const struct RingBufferT {
|
||||
usize OFFSET;
|
||||
usize SIZE;
|
||||
usize LEN;
|
||||
} *const RingBufferT;
|
||||
|
||||
struct RingBufferHead {
|
||||
usize len;
|
||||
usize start;
|
||||
};
|
||||
|
||||
|
||||
usize RingBufferEmpty(RingBufferT T, struct RingBufferHead *head);
|
||||
|
||||
void *RingBufferGet(
|
||||
RingBufferT T,
|
||||
struct RingBufferHead *head,
|
||||
size_t i
|
||||
usize i
|
||||
);
|
||||
|
||||
void *RingBufferNext(RingBufferT T, struct RingBufferHead *head);
|
||||
|
@ -48,9 +46,9 @@ void RingBufferTransfer(
|
|||
struct RingBufferHead *tmp
|
||||
);
|
||||
|
||||
size_t RingBufferOut(
|
||||
usize RingBufferOut(
|
||||
RingBufferT T,
|
||||
size_t n,
|
||||
usize n,
|
||||
void *dest,
|
||||
struct RingBufferHead *src
|
||||
);
|
47
source/fumoengine/include/vector.c
Normal file
47
source/fumoengine/include/vector.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "vector.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
bool CreateVector(VectorT T, struct Vector *vec)
|
||||
{
|
||||
void *array = malloc(16 * T->SIZE);
|
||||
|
||||
if (array == nullptr)
|
||||
return false;
|
||||
|
||||
*vec = (struct Vector) {
|
||||
.len = 0,
|
||||
.capacity = 16,
|
||||
.array = array
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeVector(struct Vector *vec)
|
||||
{
|
||||
free(vec->array);
|
||||
}
|
||||
|
||||
void *VectorGet(VectorT T, struct Vector *vec, usize i)
|
||||
{
|
||||
return (u8 *)vec->array + i * T->SIZE;
|
||||
}
|
||||
|
||||
bool VectorAdd(VectorT T, struct Vector *vec, void *item)
|
||||
{
|
||||
if (vec->len == vec->capacity) {
|
||||
usize new_capacity = vec->capacity * 2;
|
||||
void *new_array = realloc(vec->array, new_capacity * T->SIZE);
|
||||
|
||||
if (new_array == nullptr)
|
||||
return false;
|
||||
|
||||
vec->capacity = new_capacity;
|
||||
}
|
||||
|
||||
memcpy(VectorGet(T, vec, vec->len++), item, T->SIZE);
|
||||
|
||||
return true;
|
||||
}
|
26
source/fumoengine/include/vector.h
Normal file
26
source/fumoengine/include/vector.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "fumocommon.h"
|
||||
|
||||
#define VECTOR_T(VEC_ITEM_T) \
|
||||
(&(struct VectorT) { \
|
||||
.SIZE = sizeof(VEC_ITEM_T) \
|
||||
}) \
|
||||
|
||||
|
||||
typedef const struct VectorT {
|
||||
usize SIZE;
|
||||
} *const VectorT;
|
||||
|
||||
struct Vector {
|
||||
usize len;
|
||||
usize capacity;
|
||||
void *array;
|
||||
};
|
||||
|
||||
|
||||
bool CreateVector(VectorT T, struct Vector *vec);
|
||||
|
||||
void FreeVector(struct Vector *vec);
|
||||
|
||||
void *VectorGet(VectorT T, struct Vector *vec, usize i);
|
||||
|
||||
bool VectorAdd(VectorT T, struct Vector *vec, void *item);
|
|
@ -120,6 +120,20 @@ bool ControllerMap(struct Controller *ctrl, u16f code, u16f bind, u16f type)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ControllerMapMulti(
|
||||
struct Controller *ctrl,
|
||||
usize n_maps,
|
||||
struct ControlMapping *maps
|
||||
) {
|
||||
for (usize i = 0; i < n_maps; i++) {
|
||||
struct ControlMapping *map = maps + i;
|
||||
if (!ControllerMap(ctrl, map->code, map->bind, map->type))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct InputAxis *ControllerGet(struct Controller *ctrl, u16f code, u16f type)
|
||||
{
|
||||
struct ctrl_bkt *code_bkt = find(&ctrl->codes, as_id(code, type));
|
||||
|
|
|
@ -57,8 +57,8 @@ struct Controller {
|
|||
struct ctrl_dict binds;
|
||||
};
|
||||
|
||||
struct ControlBind {
|
||||
int code;
|
||||
struct ControlMapping {
|
||||
u16 code;
|
||||
u16 bind;
|
||||
u16 type;
|
||||
};
|
||||
|
@ -69,6 +69,12 @@ void FreeController(struct Controller *ctrl);
|
|||
|
||||
bool ControllerMap(struct Controller *ctrl, u16f code, u16f bind, u16f type);
|
||||
|
||||
bool ControllerMapMulti(
|
||||
struct Controller *ctrl,
|
||||
usize n_maps,
|
||||
struct ControlMapping *maps
|
||||
);
|
||||
|
||||
struct InputAxis *ControllerGet(struct Controller *ctrl, u16f code, u16f type);
|
||||
|
||||
void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs);
|
||||
|
|
|
@ -4,17 +4,8 @@
|
|||
#include "platform.h"
|
||||
|
||||
|
||||
RingBufferT IO_BUF_T = RINGBUF_T_INIT(
|
||||
struct RecordBuffer,
|
||||
struct InputRecord,
|
||||
IO_BUF_SIZE
|
||||
);
|
||||
|
||||
RingBufferT STR_BUF_T = RINGBUF_T_INIT(
|
||||
struct StringBuffer,
|
||||
char,
|
||||
STR_BUF_SIZE
|
||||
);
|
||||
RingBufferT IO_BUF_T = RINGBUF_T(struct InputRecord, IO_BUF_SIZE);
|
||||
RingBufferT STR_BUF_T = RINGBUF_T(char, STR_BUF_SIZE);
|
||||
|
||||
|
||||
void *input_worker(void *arg)
|
||||
|
@ -54,7 +45,7 @@ void *input_worker(void *arg)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool BeginInputThread(struct InputHandle *hand)
|
||||
bool CreateInputThread(struct InputHandle *hand)
|
||||
{
|
||||
*hand = (struct InputHandle) {
|
||||
.recs.head = RINGBUF_HEAD_INIT,
|
||||
|
|
|
@ -100,7 +100,7 @@ struct InputHandle {
|
|||
bool is_terminating;
|
||||
};
|
||||
|
||||
bool BeginInputThread(struct InputHandle *hand);
|
||||
bool CreateInputThread(struct InputHandle *hand);
|
||||
|
||||
bool EndInputThread(struct InputHandle *hand);
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
#include "terminal.h"
|
||||
#include <string.h>
|
||||
|
||||
#define RESET_STR_LEN 7
|
||||
#define MAX_CH4_LEN 11
|
||||
|
||||
|
||||
usize TerminalStringSize(usize wid, usize hgt)
|
||||
usize TerminalMaxOut(struct Terminal *term)
|
||||
{
|
||||
return RESET_STR_LEN
|
||||
+ MAX_CH4_LEN * wid * hgt
|
||||
+ hgt
|
||||
+ MAX_CH4_LEN * term->wid * term->hgt
|
||||
+ term->hgt
|
||||
+ 1;
|
||||
}
|
||||
|
||||
|
@ -23,7 +24,7 @@ bool CreateTerminal(struct Terminal *term, usize wid, usize hgt)
|
|||
.wid = wid,
|
||||
.hgt = hgt,
|
||||
|
||||
.ch4s = ch4s
|
||||
.buf = ch4s
|
||||
};
|
||||
|
||||
return true;
|
||||
|
@ -31,10 +32,10 @@ bool CreateTerminal(struct Terminal *term, usize wid, usize hgt)
|
|||
|
||||
void FreeTerminal(struct Terminal *term)
|
||||
{
|
||||
free(term->ch4s);
|
||||
free(term->buf);
|
||||
}
|
||||
|
||||
usize u8_to_buf(char *buf, u8f x)
|
||||
usize u8_to_str(char *out, u8f x)
|
||||
{
|
||||
usize len = 1;
|
||||
|
||||
|
@ -51,17 +52,17 @@ usize u8_to_buf(char *buf, u8f x)
|
|||
hnds = tens / 10;
|
||||
len = 3;
|
||||
|
||||
buf[0] = hnds + 48;
|
||||
buf[1] = tens + 48;
|
||||
buf[2] = ones + 48;
|
||||
out[0] = hnds + 48;
|
||||
out[1] = tens + 48;
|
||||
out[2] = ones + 48;
|
||||
} else {
|
||||
len = 2;
|
||||
|
||||
buf[0] = tens + 48;
|
||||
buf[1] = ones + 48;
|
||||
out[0] = tens + 48;
|
||||
out[1] = ones + 48;
|
||||
}
|
||||
} else {
|
||||
buf[0] = x + 48;
|
||||
out[0] = x + 48;
|
||||
}
|
||||
|
||||
return len;
|
||||
|
@ -77,57 +78,57 @@ u8f ansi_fg(u8f fg)
|
|||
return fg + (fg < 8 ? 30 : 82);
|
||||
}
|
||||
|
||||
usize ch4_dif_to_buf(char *buf, struct Color4 *dif, struct Char4 *ch4)
|
||||
usize ch4_dif_to_str(char *out, struct Color4 *dif, struct Char4 *ch4)
|
||||
{
|
||||
usize len = 0;
|
||||
|
||||
if (dif->bg != ch4->color.bg) {
|
||||
buf[len++] = '\x1b';
|
||||
buf[len++] = '[';
|
||||
len += u8_to_buf(buf + len, ansi_bg(ch4->color.bg));
|
||||
out[len++] = '\x1b';
|
||||
out[len++] = '[';
|
||||
len += u8_to_str(out + len, ansi_bg(ch4->color.bg));
|
||||
|
||||
if (dif->fg != ch4->color.fg) {
|
||||
buf[len++] = ';';
|
||||
len += u8_to_buf(buf + len, ansi_fg(ch4->color.fg));
|
||||
out[len++] = ';';
|
||||
len += u8_to_str(out + len, ansi_fg(ch4->color.fg));
|
||||
}
|
||||
|
||||
buf[len++] = 'm';
|
||||
out[len++] = 'm';
|
||||
|
||||
} else if (dif->fg != ch4->color.fg) {
|
||||
buf[len++] = '\x1b';
|
||||
buf[len++] = '[';
|
||||
len += u8_to_buf(buf + len, ansi_fg(ch4->color.fg));
|
||||
buf[len++] = 'm';
|
||||
out[len++] = '\x1b';
|
||||
out[len++] = '[';
|
||||
len += u8_to_str(out + len, ansi_fg(ch4->color.fg));
|
||||
out[len++] = 'm';
|
||||
}
|
||||
|
||||
buf[len++] = ch4->ch;
|
||||
out[len++] = ch4->ch;
|
||||
*dif = ch4->color;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
usize TerminalPrint(char *buf, usize n, struct Terminal *term)
|
||||
usize TerminalPrint(struct Terminal *term, char *out, usize n)
|
||||
{
|
||||
struct Char4 dif;
|
||||
struct Color4 dif = { 0, 0 };
|
||||
|
||||
usize len = 7;
|
||||
memcpy(buf, "\x1b[H\x1b[0m", 7);
|
||||
memcpy(out, "\x1b[H\x1b[0m", 7);
|
||||
|
||||
for (usize y = 0; y < term->hgt; y++) {
|
||||
for (usize x = 0; x < term->wid; x++) {
|
||||
usize i = y * term->wid + x;
|
||||
struct Char4 *ch4 = &term->ch4s[i];
|
||||
struct Char4 *ch4 = &term->buf[i];
|
||||
|
||||
// DEBUG
|
||||
if (ch4->ch == 0)
|
||||
ch4->ch = '#';
|
||||
// DEBUG
|
||||
|
||||
len += ch4_dif_to_buf(buf + len, &dif, ch4);
|
||||
len += ch4_dif_to_str(out + len, &dif, ch4);
|
||||
}
|
||||
buf[len++] = '\n';
|
||||
out[len++] = '\n';
|
||||
}
|
||||
|
||||
buf[len] = 0;
|
||||
out[len] = 0;
|
||||
return len;
|
||||
}
|
|
@ -22,11 +22,13 @@ struct Terminal {
|
|||
usize wid;
|
||||
usize hgt;
|
||||
|
||||
struct Char4 *ch4s;
|
||||
struct Char4 *buf;
|
||||
};
|
||||
|
||||
usize TerminalMaxOut(struct Terminal *term);
|
||||
|
||||
bool CreateTerminal(struct Terminal *term, usize wid, usize hgt);
|
||||
|
||||
void FreeTerminal(struct Terminal *term);
|
||||
|
||||
usize TerminalPrint(char *buf, usize n, struct Terminal *term);
|
||||
usize TerminalPrint(struct Terminal *term, char *out, usize n);
|
|
@ -1,114 +1,35 @@
|
|||
#include "fumocommon.h"
|
||||
#include "fumoengine.h"
|
||||
#include "fumotris.h"
|
||||
|
||||
|
||||
enum ControlCode {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
SOFT_DROP,
|
||||
HARD_DROP,
|
||||
ROTATE_CCW,
|
||||
ROTATE_CW,
|
||||
ROTATE_180,
|
||||
SWAP,
|
||||
ESC,
|
||||
VSCROLL,
|
||||
HSCROLL,
|
||||
MOUSE
|
||||
};
|
||||
|
||||
#define CODE_COUNT 12
|
||||
|
||||
const struct ControlBind ctrl_binds[12] = {
|
||||
{ LEFT, 0x25, BUTTON },
|
||||
{ RIGHT, 0x27, BUTTON },
|
||||
{ SOFT_DROP, 0x28, BUTTON },
|
||||
{ HARD_DROP, 0x20, BUTTON },
|
||||
{ ROTATE_CCW, 'Z', BUTTON },
|
||||
{ ROTATE_CW, 'X', BUTTON },
|
||||
{ ROTATE_180, 'A', BUTTON },
|
||||
{ SWAP, 'C', BUTTON },
|
||||
{ ESC, 0x1B, BUTTON },
|
||||
{ VSCROLL, 0, AXIS },
|
||||
{ HSCROLL, 1, AXIS },
|
||||
{ MOUSE, 0, JOYSTICK }
|
||||
};
|
||||
|
||||
void Loop(struct FumoGame *game)
|
||||
void Update(struct FumoInstance *instance, void *args)
|
||||
{
|
||||
while (true) {
|
||||
game->time = TimeNow();
|
||||
struct Fumotris *game = args;
|
||||
|
||||
if (!InputAquire(&game->input_hand))
|
||||
Panic("Aquire failed");
|
||||
TetrMapDraw(&game->board, &instance->term);
|
||||
}
|
||||
|
||||
ControllerPoll(&game->ctrl, &game->input_hand.recs);
|
||||
bool CreateFumotris(struct Fumotris *game)
|
||||
{
|
||||
if (!CreateTetrMap(&game->board, 10, 10))
|
||||
return false;
|
||||
|
||||
if (!InputRelease(&game->input_hand))
|
||||
Panic("Release failed");
|
||||
|
||||
|
||||
|
||||
EventInvoke(&game->update, 0);
|
||||
|
||||
_sleep(100);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct FumoGame game;
|
||||
FumoInit(&game);
|
||||
struct FumoInstance instance;
|
||||
CreateFumoInstance(&instance);
|
||||
|
||||
for (size_t i = 0; i < CODE_COUNT; i++) {
|
||||
const struct ControlBind *bind = &ctrl_binds[i];
|
||||
ControllerMap(&game.ctrl, bind->code, bind->bind, bind->type);
|
||||
}
|
||||
struct Fumotris game;
|
||||
CreateFumotris(&game);
|
||||
|
||||
Loop(&game);
|
||||
ControllerMapMulti(&instance.ctrl, CODE_COUNT, MAPPINGS);
|
||||
|
||||
FumoInstanceHook(&instance.on_update, Update, &game);
|
||||
|
||||
|
||||
FumoInstanceRun(&instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*const u8 I[16] = {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
1, 1, 1, 1,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
const u8 O[4] = {
|
||||
1, 1,
|
||||
1, 1
|
||||
};
|
||||
|
||||
const u8 T[9] = {
|
||||
0, 1, 0,
|
||||
1, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 S[9] = {
|
||||
0, 1, 1,
|
||||
1, 1, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 Z[9] = {
|
||||
1, 1, 0,
|
||||
0, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 J[9] = {
|
||||
1, 0, 0,
|
||||
1, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 L[9] = {
|
||||
0, 0, 1,
|
||||
1, 1, 1,
|
||||
0, 0, 0
|
||||
};*/
|
84
source/fumotris/fumotris.h
Normal file
84
source/fumotris/fumotris.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include "fumocommon.h"
|
||||
#include "fumoengine.h"
|
||||
#include "tetr.h"
|
||||
|
||||
|
||||
#define CODE_COUNT 12
|
||||
|
||||
enum ControlCode {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
SOFT_DROP,
|
||||
HARD_DROP,
|
||||
ROTATE_CCW,
|
||||
ROTATE_CW,
|
||||
ROTATE_180,
|
||||
SWAP,
|
||||
ESC,
|
||||
VSCROLL,
|
||||
HSCROLL,
|
||||
MOUSE
|
||||
};
|
||||
|
||||
struct ControlMapping MAPPINGS[12] = {
|
||||
{ LEFT, 0x25, BUTTON },
|
||||
{ RIGHT, 0x27, BUTTON },
|
||||
{ SOFT_DROP, 0x28, BUTTON },
|
||||
{ HARD_DROP, 0x20, BUTTON },
|
||||
{ ROTATE_CCW, 'Z', BUTTON },
|
||||
{ ROTATE_CW, 'X', BUTTON },
|
||||
{ ROTATE_180, 'A', BUTTON },
|
||||
{ SWAP, 'C', BUTTON },
|
||||
{ ESC, 0x1B, BUTTON },
|
||||
{ VSCROLL, 0, AXIS },
|
||||
{ HSCROLL, 1, AXIS },
|
||||
{ MOUSE, 0, JOYSTICK }
|
||||
};
|
||||
|
||||
|
||||
struct Fumotris {
|
||||
struct TetrMap board;
|
||||
struct TetrMap piece;
|
||||
};
|
||||
|
||||
const u8 I[16] = {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
1, 1, 1, 1,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
const u8 O[4] = {
|
||||
1, 1,
|
||||
1, 1
|
||||
};
|
||||
|
||||
const u8 T[9] = {
|
||||
0, 1, 0,
|
||||
1, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 S[9] = {
|
||||
0, 1, 1,
|
||||
1, 1, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 Z[9] = {
|
||||
1, 1, 0,
|
||||
0, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 J[9] = {
|
||||
1, 0, 0,
|
||||
1, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const u8 L[9] = {
|
||||
0, 0, 1,
|
||||
1, 1, 1,
|
||||
0, 0, 0
|
||||
};
|
|
@ -1,62 +1,55 @@
|
|||
#include <iso646.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fumocommon.h"
|
||||
#include "term.h"
|
||||
#include "tetr.h"
|
||||
|
||||
|
||||
struct TetrMap {
|
||||
size_t wid;
|
||||
size_t hgt;
|
||||
size_t area;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
u8 rot;
|
||||
|
||||
u8 *blks;
|
||||
};
|
||||
|
||||
struct TetrMap NewTetrMap(u8 *blks, size_t wid, size_t hgt)
|
||||
bool CreateTetrMap(struct TetrMap *map, usize wid, usize hgt)
|
||||
{
|
||||
size_t area = wid * hgt;
|
||||
memset(blks, 0, area);
|
||||
u8 *blks = calloc(wid * hgt, sizeof(u8));
|
||||
|
||||
return (struct TetrMap) {
|
||||
wid, hgt, area,
|
||||
0, 0, 0,
|
||||
blks
|
||||
if (blks == nullptr)
|
||||
return false;
|
||||
|
||||
*map = (struct TetrMap) {
|
||||
.wid = wid,
|
||||
.hgt = hgt,
|
||||
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
|
||||
.rot = 0,
|
||||
|
||||
.blks = blks
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TetrMapToTermBuf(struct TetrMap *map, struct Terminal *term)
|
||||
void FreeTetrMap(struct TetrMap *map)
|
||||
{
|
||||
free(map->blks);
|
||||
}
|
||||
|
||||
void TetrMapDraw(struct TetrMap *map, struct Terminal *term)
|
||||
{
|
||||
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
|
||||
|
||||
for (size_t y = 0; y < map->hgt; y++) {
|
||||
for (size_t x = 0; x < map->wid; x++) {
|
||||
size_t map_i = y * map->wid + x;
|
||||
size_t buf_i = (y + map->y) * term->wid + (x + map->x) * 2;
|
||||
for (usize y = 0; y < map->hgt; y++) {
|
||||
for (usize x = 0; x < map->wid; x++) {
|
||||
usize map_i = y * map->wid + x;
|
||||
usize term_i = (y + map->y) * term->wid + (x + map->x) * 2;
|
||||
|
||||
struct Char4 *a = &term->ch4s[buf_i];
|
||||
struct Char4 *b = &term->ch4s[buf_i + 1];
|
||||
struct Char4 *block = term->buf + term_i;
|
||||
|
||||
if (map->blks[map_i] == 0) {
|
||||
a->ch = '(';
|
||||
b->ch = ')';
|
||||
block[0].ch = '(';
|
||||
block[1].ch = ')';
|
||||
} else {
|
||||
a->ch = '[';
|
||||
b->ch = ']';
|
||||
block[0].ch = '[';
|
||||
block[1].ch = ']';
|
||||
}
|
||||
|
||||
u8 fg = blk_colors[map->blks[map_i]];
|
||||
a->fg = fg;
|
||||
b->fg = fg;
|
||||
block[0].color.fg = fg;
|
||||
block[1].color.fg = fg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
#include <iso646.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fumocommon.h"
|
||||
#include "term.h"
|
||||
#include "terminal.h"
|
||||
|
||||
|
||||
struct TetrMap {
|
||||
size_t wid;
|
||||
size_t hgt;
|
||||
size_t area;
|
||||
usize wid;
|
||||
usize hgt;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
u8 rot;
|
||||
|
||||
u8f rot;
|
||||
|
||||
u8 *blks;
|
||||
};
|
||||
|
||||
struct TetrMap NewTetrMap(u8 *blks, size_t wid, size_t hgt);
|
||||
bool CreateTetrMap(struct TetrMap *map, usize wid, usize hgt);
|
||||
|
||||
void TetrMapToTermBuf(struct TetrMap *map, struct Terminal *term);
|
||||
void FreeTetrMap(struct TetrMap *map);
|
||||
|
||||
void TetrMapDraw(struct TetrMap *map, struct Terminal *term);
|
||||
|
||||
bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy);
|
Loading…
Reference in a new issue