Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Commander ($) operator and utils. #77

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static bool orca_is_valid_glyph(Glyph c) {
case ';':
case '=':
case '?':
case '$':
return true;
}
return false;
Expand Down
14 changes: 11 additions & 3 deletions cli_main.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "base.h"
#include "state.h"
#include "field.h"
#include "gbuffer.h"
#include "sim.h"
Expand Down Expand Up @@ -85,11 +85,19 @@ int main(int argc, char **argv) {
Oevent_list oevent_list;
oevent_list_init(&oevent_list);
Usz max_ticks = (Usz)ticks;

State state;
state.tick_num = 0;
state.bpm = (Usz) 120;
state.oosc_dev = NULL;
state.is_playing = true;

for (Usz i = 0; i < max_ticks; ++i) {
state.tick_num = i;
mbuffer_clear(mbuf_r.buffer, field.height, field.width);
oevent_list_clear(&oevent_list);
orca_run(field.buffer, mbuf_r.buffer, field.height, field.width, i,
&oevent_list, 0);
orca_run(field.buffer, mbuf_r.buffer, field.height, field.width,
&oevent_list, 0, &state);
}
mbuf_reusable_deinit(&mbuf_r);
oevent_list_deinit(&oevent_list);
Expand Down
48 changes: 48 additions & 0 deletions commander.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "commander.h"
#include <stdlib.h>
#include <string.h>

void parse_command(Glyph *command, State *state) {
const Glyph end_line[2] = ".";
Glyph *token;
token = strtok(command, end_line);
while (token != NULL) {
// Parse simple tokens
if (strcmp(token, "play") == 0) {
state->is_playing = true;
} else if (strcmp(token, "stop") == 0) {
state->is_playing = false;
} else if (strcmp(token, "run") == 0) {
state->tick_num++;
} else {
const Glyph arguments_separator[2] = ":";
token = strtok(command, arguments_separator);
while(token != NULL) {
// TODO handle errors: https://stackoverflow.com/questions/15229411/input-validation-of-an-integer-using-atoi
if (strcmp(token, "bpm") == 0) {
token = strtok(NULL, end_line);
if (token == NULL) return;
Glyph *end_ptr;
state->bpm = (Usz) strtoul(token, &end_ptr, 10);
} else if (strcmp(token, "frame") == 0) {
token = strtok(NULL, end_line);
if (token == NULL) return;
Glyph *end_ptr;
state->tick_num = (Usz) strtoul(token, &end_ptr, 10);
} else if (strcmp(token, "rewind") == 0) {
token = strtok(NULL, end_line);
if (token == NULL) return;
Glyph *end_ptr;
state->tick_num -= (Usz) strtoul(token, &end_ptr, 10);
} else if (strcmp(token, "skip") == 0) {
token = strtok(NULL, end_line);
if (token == NULL) return;
Glyph *end_ptr;
state->tick_num += (Usz) strtoul(token, &end_ptr, 10);
}
token = strtok(NULL, arguments_separator);
}
}
token = strtok(NULL, end_line);
}
}
5 changes: 5 additions & 0 deletions commander.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once
#include "base.h"
#include "state.h"

void parse_command(Glyph *command, State *state);
53 changes: 41 additions & 12 deletions sim.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "sim.h"
#include "commander.h"
#include "gbuffer.h"

//////// Utilities
Expand Down Expand Up @@ -98,15 +99,15 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
OPER_FUNCTION_ATTRIBS oper_behavior_##_oper_name( \
Glyph *const restrict gbuffer, Mark *const restrict mbuffer, \
Usz const height, Usz const width, Usz const y, Usz const x, \
Usz Tick_number, Oper_extra_params *const extra_params, \
State *state, Oper_extra_params *const extra_params, \
Mark const cell_flags, Glyph const This_oper_char) { \
(void)gbuffer; \
(void)mbuffer; \
(void)height; \
(void)width; \
(void)y; \
(void)x; \
(void)Tick_number; \
(void)state; \
(void)extra_params; \
(void)cell_flags; \
(void)This_oper_char;
Expand Down Expand Up @@ -155,7 +156,8 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
_(':', midi) \
_(';', udp) \
_('=', osc) \
_('?', midipb)
_('?', midipb) \
_('$', commander)

#define ALPHA_OPERATORS(_) \
_('A', add) \
Expand Down Expand Up @@ -397,6 +399,33 @@ BEGIN_OPERATOR(midipb)
oe->lsb = (U8)(index_of(lsb_g) * 127 / 35);
END_OPERATOR

BEGIN_OPERATOR(commander)
Usz n = width - x - 1;
if (n > 16)
n = 16;
Glyph const *restrict gline = gbuffer + y * width + x + 1;
Mark *restrict mline = mbuffer + y * width + x + 1;
Glyph cpy[Oevent_udp_string_count];
Usz i;
for (i = 0; i < n; ++i) {
Glyph g = gline[i];
if (g == '.')
break;
cpy[i] = g;
mline[i] |= Mark_flag_lock;
}
n = i;

STOP_IF_NOT_BANGED;

// Handle empty cases
// TODO revise if necessary
if (PEEK(0, 1) == '.') return;

parse_command(cpy, state);

END_OPERATOR

BEGIN_OPERATOR(add)
LOWERCASE_REQUIRES_BANG;
PORT(0, -1, IN | PARAM);
Expand Down Expand Up @@ -432,7 +461,7 @@ BEGIN_OPERATOR(clock)
rate = 1;
if (mod_num == 0)
mod_num = 8;
Glyph g = glyph_of(Tick_number / rate % mod_num);
Glyph g = glyph_of(state->tick_num / rate % mod_num);
POKE(1, 0, g);
END_OPERATOR

Expand All @@ -447,7 +476,7 @@ BEGIN_OPERATOR(delay)
rate = 1;
if (mod_num == 0)
mod_num = 8;
Glyph g = Tick_number % (rate * mod_num) == 0 ? '*' : '.';
Glyph g = state->tick_num % (rate * mod_num) == 0 ? '*' : '.';
POKE(1, 0, g);
END_OPERATOR

Expand Down Expand Up @@ -633,7 +662,7 @@ BEGIN_OPERATOR(random)
}
// Initial input params for the hash
Usz key = (extra_params->random_seed + y * width + x) ^
(Tick_number << UINT32_C(16));
(state->tick_num << UINT32_C(16));
// 32-bit shift_mult hash to evenly distribute bits
key = (key ^ UINT32_C(61)) ^ (key >> UINT32_C(16));
key = key + (key << UINT32_C(3));
Expand Down Expand Up @@ -676,7 +705,7 @@ BEGIN_OPERATOR(uclid)
Usz max = index_of(PEEK(0, 1));
if (max == 0)
max = 8;
Usz bucket = (steps * (Tick_number + max - 1)) % max + steps;
Usz bucket = (steps * (state->tick_num + max - 1)) % max + steps;
Glyph g = (bucket >= max) ? '*' : '.';
POKE(1, 0, g);
END_OPERATOR
Expand Down Expand Up @@ -743,7 +772,7 @@ END_OPERATOR
//////// Run simulation

void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width,
Usz tick_number, Oevent_list *oevent_list, Usz random_seed) {
Oevent_list *oevent_list, Usz random_seed, State *state) {
Glyph vars_slots[Glyphs_index_count];
memset(vars_slots, '.', sizeof(vars_slots));
Oper_extra_params extras;
Expand All @@ -764,15 +793,15 @@ void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width,
switch (glyph_char) {
#define UNIQUE_CASE(_oper_char, _oper_name) \
case _oper_char: \
oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, tick_number, \
&extras, cell_flags, glyph_char); \
oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, state, \
&extras, cell_flags, glyph_char); \
break;

#define ALPHA_CASE(_upper_oper_char, _oper_name) \
case _upper_oper_char: \
case (char)(_upper_oper_char | 1 << 5): \
oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, tick_number, \
&extras, cell_flags, glyph_char); \
oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, state, \
&extras, cell_flags, glyph_char); \
break;
UNIQUE_OPERATORS(UNIQUE_CASE)
ALPHA_OPERATORS(ALPHA_CASE)
Expand Down
5 changes: 2 additions & 3 deletions sim.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once
#include "base.h"
#include "state.h"
#include "vmio.h"

void orca_run(Glyph *restrict gbuffer, Mark *restrict mbuffer, Usz height,
Usz width, Usz tick_number, Oevent_list *oevent_list,
Usz random_seed);
Usz width, Oevent_list *oevent_list, Usz random_seed, State *state);
11 changes: 11 additions & 0 deletions state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "base.h"
#include "osc_out.h"

typedef struct {
Usz tick_num;
Usz bpm;
bool is_playing : 1;
Oosc_dev *oosc_dev;

} State;
2 changes: 1 addition & 1 deletion sysmisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Conf_read_result conf_read_line(FILE *file, char *buf, Usz bufsize,
if (a0 == len)
goto ignore;
char c = s[a0];
if (c == ';' || c == '#') // comment line, ignore
if (c == ';' || c == '#' || c == '$') // comment line, ignore
goto ignore;
if (c == '=') // '=' before any other char, bad
goto ignore;
Expand Down
2 changes: 1 addition & 1 deletion tool
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ build_target() {
out_exe=cli
;;
orca|tui)
add source_files osc_out.c term_util.c sysmisc.c thirdparty/oso.c tui_main.c
add source_files commander.c osc_out.c term_util.c sysmisc.c thirdparty/oso.c tui_main.c
add cc_flags -D_XOPEN_SOURCE_EXTENDED=1
# thirdparty headers (like sokol_time.h) should get -isystem for their
# include dir so that any warnings they generate with our warning flags
Expand Down
Loading