B!Vamos!
If people are going to program custom fonts and graphics in Hauki BASIC, they
need more than just a PRINT command. They need Memory (variables) and Time (a
game loop).
Let's make Hauki BASIC Turing Complete.
For v0.2, I have written a C string-parser that adds:
* Variables: A through Z are now active memory registers.
* Math: You can now do assignment and addition/subtraction (X = X + 2).
* Logic: IF X > 200 THEN... (We have conditional branching!)
* Control Flow: GOTO 30 (Infinite loops!).
* Screen Sync: VSYNC (Pushes the backbuffer to the VGA and pauses briefly, so
the loop doesn't run at 10 million FPS and tear the screen).
* The Missing Dot: I explicitly coded ASCII 46 (.) into the font array so you
can officially print "V0.2"!
Run x-approve to inject the new parser. I also included a new test script that
proves the language can run a game loop by moving text across the screen!
[DEPLOY-OMEGA-START]
#!/usr/bin/env bash
# DEDUP-BUSTER: hauki-basic-v0.2
# TARGET-NODE: hetzner-native
# DESCRIPTION: Adds Variables, IF statements, Math, GOTO, and VSYNC to Hauki
BASIC.
cd /home/ai-streamer/x-projects/hauki_os_3 || exit 1
echo "=================================================="
echo "=================================================="' UPGRADING HAUKI
BASIC TO V0.2 (TURING COMPLETE)"
echo "=================================================="
cat << 'EOF' > src/modules/hbasic/hbasic.c
/ HAUKI BASIC INTERPRETER V0.2
/ Added: Variables, Math, IF, GOTO, VSYNC, and the "." character!
void sys_print(const char* str) { int ret; asm volatile("int $0x80" :
"=a"(ret) : "a"(3), "b"((int)str) : "memory"); }
void sys_clear() { int ret; asm volatile("int $0x80" : "=a"(ret) : "a"(4) :
"memory"); }
void sys_vga_mode(int mode) { int ret; asm volatile("int $0x80" : "=a"(ret) :
"a"(6), "b"(mode) : "memory"); }
unsigned char inb(unsigned short port) { unsigned char ret; asm volatile("inb
%1, %0" : "=a"(ret) : "Nd"(port)); return ret; }
unsigned char backbuffer[64000];
int vars[26] = {0}; // Variables A-Z
/ --- FONT ENGINE (Now with 100% more dots!) ---
const unsigned char font8x8[][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 32: Space
{0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00}, // 33: !
{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18}, // 46: . (THE DOT!)
{0},
{0x3C,0x66,0x6E,0x76,0x66,0x66,0x3C,0x00}, // 48: 0
{0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00}, // 49: 1
{0x3C,0x66,0x06,0x0C,0x18,0x30,0x7E,0x00}, // 50: 2
{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 51: 3
{0x0C,0x1C,0x3C,0x6C,0x7E,0x0C,0x0C,0x00}, // 52: 4
{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 53: 5
{0x3C,0x60,0x7C,0x66,0x66,0x66,0x3C,0x00}, // 54: 6
{0x7E,0x06,0x0C,0x18,0x30,0x30,0x30,0x00}, // 55: 7
{0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 56: 8
{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 57: 9
{0}, {0}, {0}, {0}, {0}, {0}, {0},
{0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00}, // 65: A
{0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00}, // 66: B
{0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00}, // 67: C
{0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00}, // 68: D
{0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xFE,0x00}, // 69: E
{0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xC0,0x00}, // 70: F
{0x3E,0x60,0xC0,0xCE,0xC6,0x66,0x3E,0x00}, // 71: G
{0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00}, // 72: H
{0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00}, // 73: I
{0x0E,0x06,0x06,0x06,0xC6,0xC6,0x7C,0x00}, // 74: J
{0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00}, // 75: K
{0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00}, // 76: L
{0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00}, // 77: M
{0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00}, // 78: N
{0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00}, // 79: O
{0xFC,0x66,0x66,0xFC,0xC0,0xC0,0xC0,0x00}, // 80: P
{0x38,0x6C,0xC6,0xC6,0xDA,0xCC,0x76,0x00}, // 81: Q
{0xFC,0x66,0x66,0xFC,0xD8,0xCC,0xC6,0x00}, // 82: R
{0x3E,0x60,0x60,0x3C,0x06,0x06,0x7C,0x00}, // 83: S
{0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, // 84: T
{0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00}, // 85: U
{0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00}, // 86: V
{0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00}, // 87: W
{0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00}, // 88: X
{0xC6,0xC6,0xC6,0x7C,0x18,0x18,0x18,0x00}, // 89: Y
{0xFE,0x06,0x0C,0x18,0x30,0x60,0xFE,0x00} // 90: Z
};
void draw_char(int x, int y, char c, unsigned char col) {
if(c < 32 || c > 90) return;
const unsigned char* glyph = font8x8[c - 32];
for(int cy=0; cy<8; cy++) for(int cx=0; cx<8; cx++) {
if(glyph[cy] & (1 << (7 - cx))) {
int px = x + cx, py = y + cy;
if(px>=0 && px<320 && py>=0 && py<200) backbuffer[py*320+px] =
col;
}
}
}
void draw_string(int x, int y, const char* str, unsigned char col) {
int px = x; while(*str) { draw_char(px, y, *str, col); px += 8; str++; }
}
/ --- BASIC PARSER HELPERS ---
int match(const char* p, const char* word) {
while(*word) { if(*p != *word) return 0; p++; word++; }
return 1;
}
int parse_int(const char** str) {
int val = 0;
while(**str == ' ' || **str == ',') (*str)++;
while(**str >= '0' && **str <= '9') { val = val * 10 + (**str - '0');
(*str)++; }
return val;
}
int get_val(const char** p) {
while(**p == ' ' || **p == ',') (*p)++;
int sign = 1;
if (**p == '-') { sign = -1; (*p)++; }
if (**p >= 'A' && **p <= 'Z') { int v = vars[**p - 'A']; (*p)++; return v
* sign; }
return parse_int(p) * sign;
}
void parse_string(const char** str, char* out) {
while(**str == ' ' || **str == ',') (*str)++;
if (**str == '"') {
(*str)++; int idx = 0;
while(**str != '"' && **str != '\0') { out[idx++] = **str; (*str)++; }
out[idx] = '\0';
if (**str == '"') (*str)++;
}
}
const char* find_line(const char* src, int target) {
const char* p = src;
while(*p) {
const char* line_start = p;
int num = parse_int(&p);
if (num == target) return line_start;
while(*p && *p != '
') p++;
if (*p == '
') p++;
}
return src;
}