Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Spell of Mastery Progress

Name: Anonymous 2020-09-17 20:05

Ok. The new voxel rendering algorithm performs 1.4 times faster. Not much, but voxel models can also be split into 16-bit chunks, which locally use only 16-bit addressing. That should speedup the algorithm further, if the bottleneck is with the memory bandwidth.

I've also discovered that GCC's __builtin_popcount is slower than a lookup table, since it branches into subroutine __popcountdi2. Why GCC doesnt use the x86 popcnt opcode? No idea. No idea. But it probably would be easier to answer why Stallman molests little children.

Name: Anonymous 2020-09-17 20:28

The new voxel rendering algorithm performs 1.4 times faster.
Just assume everyone playing is running modern hardware

Name: Anonymous 2020-09-17 20:37

>>2
Poor people don't pay for games.

Name: Anonymous 2020-09-17 21:08

s/1.4 time/2.4 times

Name: Anonymous 2020-09-17 21:09

>>2
I'm using software rendering. Although it should be trivial porting it to GPU and achieving like 1000x speedup

Name: Anonymous 2020-09-17 23:09

Would you stop blaming RMS over Marvin Minsky... They were both lispers but different people.

Name: Anonymous 2020-09-18 1:16

>>6
If Epstein sent the 17 year-old girl to fuck Minsky it wasn't raep.

Name: Smell of Hamstery 2020-09-18 1:46

Smell of Hamstery

Name: Anonymous 2020-09-18 2:50

>>2
We all use Thinkpads here.

Name: Anonymous 2020-09-18 3:13

Steve Nash looked disgusting--nipples protruding--in his blue shirt at SIGPLAN. Very very disrespectful.

Name: Anonymous 2020-09-18 11:10

Nikita! Are you not locked up in a Georgian gaol?

Name: Anonymous 2020-09-19 0:01

>>11
No.

Name: Anonymous 2020-09-20 0:45

Any luck in getting the pirated sounds removed from FreeDoom?

Name: Anonymous 2020-09-20 6:42

>>13
No. They ban you when you ask about it. Same with the Wesnoth plagiarizing music from Betrayal at Krondor (for example, wanderer.ogg).


Krondor has nice music indeed, so I can't blame free software communists for stealing.

Name: Anonymous 2020-09-20 10:41

>>14
They ban you because it's a common unsubstantiated spam topic

Name: Anonymous 2020-09-21 16:49

Surprisingly the hardest part of working with lex/yacc was location tracking, which is a bit obscure. Even more surprising was discovering that simple SEXP lists from Lisp can be used to hold C/C++ parsed code, although one will have to add a bit of metainfo for holding the locations. At least for my purposes, since I want to modify them. But during writing the actual compiler, one will still need locations to report errors. Like, well, syntax errors. While C++ syntax is notorious for its monstrosity (surpassing even Haskell in difficulty), even the plain C is not context free, since the parser needs access to the context to properly create the aforementioned SEXP.


Anyway, now I can parse structs, typedefs and functions, while skipping the rest of the syntax. That should be just enough to mod the C for my purposes.

$ cat example.c
int foo(int n, int m) {
return n*m+1;
}

enum russia {govna,poesh,suka};

int bar(int n) {
return n+1;
}


$ cat example.c | ../lib/cext
function:
row,col: 1,0
type: int
name: foo
arg0: int n
arg1: int m
function:
row,col: 7,0
type: int
name: bar
arg0: int n



No. I don't need enums.

Name: Anonymous 2020-09-21 18:02

>>16
Moral: learn Lisp - it will come handy one day, even if you work solely with C/C++.

Name: Anonymous 2020-09-21 21:41

enum russia {govna,poesh,suka};
Very unpatriotic!

Name: Anonymous 2020-09-22 14:36

>>18
I'm a citizen of the world.

Name: Anonymous 2020-09-22 15:39

>>19
No your not brown BOY!

Name: Anonymous 2020-09-23 21:58

Ok. Parsing C in C was a bit more involved than I expected, even despite I flatten most of the expression and statement stuff. C syntax is not easy, but still a far cry from the nightmarish C++ syntax. GCC also adds a lot of its own special constructs, which break parser. The task would have been a lot easier with Symta or Lisp, but I want to do it with just YACC, since I will probably reuse the code in the Symta runtime, which can't use the Symta itself.

What I need is determining the type of the struct fields, then patching the accesses right before passing it to the actual C compiler.

Here is the list of node types I found unavoidable:
D(N_VOID),
D(N_BLOCK),
D(N_CAST),
D(N_CALL),
D(N_DECL),
D(N_DECLARATOR),
D(N_DOT),
D(N_EXPR),
D(N_FN),
D(N_LIT),
D(N_PARAM),
D(N_PARAM_LIST),
D(N_STRUCT),
D(N_STRUCT_DECL),
D(N_STRUCT_FIELD),
D(N_TOP),
D(N_TYPE),
D(N_TYPENAME),
D(N_TYPE_ALIGN),
D(N_TYPE_FUNC),
D(N_TYPE_QUAL),
D(N_TYPE_SPEC),
D(N_TYPE_STOR),
D(N_VARS),
D(N_VAR_DEF),
D(N_END)

Name: Anonymous 2020-09-23 22:00

>>21
Moral: C syntax is nasty and inflexible. Say each storage class and each basic type must be explicitly added into the syntax.

Name: Anonymous 2020-09-23 23:58

is the Dire Hamster unit implemented yet?

Name: Anonymous 2020-09-24 12:32

Hey Steve, I downloaded the preview version on Steam and it's a great game! I love of Spell of Mastery!
I'm stuck a level 5 though. How do I get access to the goat tower? Any hints?

Name: Anonymous 2020-09-24 12:53

Is the source available? I would like to learn from someone who is not a pink-haired open-source linuxxer.

Name: Anonymous 2020-09-24 19:33

Poast source codans?

Name: Anonymous 2020-09-24 19:33

Nikita-san, plox give .cpp files (NOT cp fles you filthy paedo)

Name: Anonymous 2020-09-24 19:34

Nikeeta (indian name for russian man?), why not produce source files so I can compile on my 2011 mac mini power pc

Name: Anonymous 2020-09-24 19:38

>>27-28
his name is steve

Name: Anonymous 2020-09-24 19:43

>>27
cp

Ask Stallman. RMS now curates the Epstein archives.

Name: Anonymous 2020-09-25 16:53

Did you know that you can do ((struct {int a; int b;}*)ptr)->b in C?

Name: Anonymous 2020-09-25 17:33

typedef int myint1, myint2; is also valid, both syntactically and semantically. This typedef applies to both declarations. I.e. myint2 becomes an alias for int, not a variable of type int.

Name: Anonymous 2020-09-25 19:54

>>31
Not just that, but you can declare a literal data item like that and immediately cast it to void or char ptr!
>>32
Yeah, that's a nod to Pascal. Per-module types were encouraged so as to clearly define the domain of each function and procedure. This remains in Ada even today.

Name: Anonymous 2020-09-25 19:56

Made typedef working. The next stage is implementing the limited C++ extensions, and then doing the patching. Obviously I dont have the time to implement the full scale GCC extensions, so I will have to work with C99 and introduce something like `#pargma nash_extensions` and `#pargma end_nash_extensions`

$ cat example.c
typedef int myint;

myint mival;

typedef struct person {
char *name;
int age;
int height;
} person;

person john;

int bar(int n, int l) {
int u=123, m = k;
return n+1;


$ cat example.c | ../lib/cext
conflicts: 2 shift/reduce
decl:
typedef int myint
decl:
myint<typedef int> mival
decl:
typedef struct person person
decl:
person<typedef struct person> john
function:
row,col: 13,0
type: int
name: bar
args: int n, int l
body:
BLOCK
decl:
int u =
int m =
ref:k
ref:n (declared)
int

}

Name: Anonymous 2020-09-26 19:21

Ok. Now upon encountering
p.suicide(now)
The parser will spit the following to stdout
mpatch:123:456:789:person_method_suicide

that basically orders the second stage patch command to patch the source at offsets 123, 456 and 789 associated with method object and method args.

A bit kludgey, but still the best I can do, without hacking the compiler itself.

Name: Anonymous 2020-09-29 20:54

A few kludges later it patches
float foo(entity *e) {
return e.xyz.x;
}

into:
float foo(entity *e) {
return vec3_m_x(&(entity_m_xyz(e)));
}


I'm surprised it works at all, given the recursive nature of rewriting!

Of course handling vec3 properly requires another hack
class !vec3;

that basically means vec3 is not a class. Since vec3 is defined as a SIMD type, my patcher knows nothing about. But I still want to define (redefine) a few methods on top of it.

Allowing overloading arithmetic operators on pointers will mean more hacks.

Name: Anonymous 2020-10-01 16:54

What can't be done by simple patching is implementing the GCC's ({...}) blocks, unless you redirect them to an external function, capturing all free variables into arguments. Since one can't have say for loop and if/else inside argument list.

Name: Anonymous 2020-10-02 5:23

>>37
({}) captures the enclosing function variables IIRC, any pointer or array using in
main(){
a[x]=*b[x];
({can reference both(thats how C "lambda" injections work) })
}
*It can capture globals and enclosing variables. Edited on 02/10/2020 05:29.

Name: Anonymous 2020-10-02 9:00

>>38
({}) captures the enclosing function variables IIRC, any pointer or array using in

No. You're speaking about Objective C blocks, which are like C++ objects, where the fields are the pointers to the refcounted environment.

Name: Anonymous 2020-10-04 10:34

Ok. Aftre some more work I have managed to make the patcher work with the actual Symta code base, and with my voxel library. Now the implementation of GLSL vec3 looks like following:

#define ME (*this)

class !vec3;
class !vec2;
class !ivec2;
class !ivec3;

INLINE float vec3.x {return ME[0];}
INLINE float vec3.y {return ME[1];}
INLINE float vec3.z {return ME[2];}

INLINE float vec3."x="(float v) {ME[0] = v; return v;}
INLINE float vec3."y="(float v) {ME[1] = v; return v;}
INLINE float vec3."z="(float v) {ME[2] = v; return v;}

INLINE float vec3."x+="(float v) {ME[0] += v; return ME[0];}
INLINE float vec3."y+="(float v) {ME[1] += v; return ME[1];}
INLINE float vec3."z+="(float v) {ME[2] += v; return ME[2];}

INLINE float vec3."x-="(float v) {ME[0] -= v; return ME[0];}
INLINE float vec3."y-="(float v) {ME[1] -= v; return ME[1];}
INLINE float vec3."z-="(float v) {ME[2] -= v; return ME[2];}

INLINE int ivec3.x {return ME[0];}
INLINE int ivec3.y {return ME[1];}
INLINE int ivec3.z {return ME[2];}

INLINE int ivec3."x="(int v) {ME[0] += v; return ME[0];}
INLINE int ivec3."y="(int v) {ME[1] += v; return ME[1];}
INLINE int ivec3."z="(int v) {ME[2] += v; return ME[2];}

INLINE int ivec3."x-="(int v) {ME[0] -= v; return ME[0];}
INLINE int ivec3."y-="(int v) {ME[1] -= v; return ME[1];}
INLINE int ivec3."z-="(int v) {ME[2] -= v; return ME[2];}


INLINE float vec2.x {return ME[0];}
INLINE float vec2.y {return ME[1];}

INLINE int ivec2.x {return ME[0];}
INLINE int ivec2.y {return ME[1];}



My only hope is that GCC can optimize `&` and `*` back to SIMD operators.

Name: Anonymous 2020-10-04 16:14

>>38
Here is how Apple implemented lambdas into C:
https://clang.llvm.org/docs/Block-ABI-Apple.html

Name: Anonymous 2020-10-05 22:28

Dire Hamster

Name: Anonymous 2020-10-06 9:11

For a long time I have been using a hashtable library made by other people. It had its drawbacks. In particular I have to acknowledge the original authors in the credits of my software, and its hash function is far from being perfect.

For example, here is their hash Bernstein function applied to the various modifications of the string "hello":
0f8fff15: hallo
0f908b76: hbllo
0f9117d7: hcllo
0f91a438: hdllo
0f923099: hello
0f92bcfa: hfllo
0f93495b: hgllo
0f93d5bc: hhllo
0f94621d: hillo
0f94ee7e: hjllo
0f957adf: hkllo
0f960740: hlllo
0f9693a1: hmllo
0f972002: hnllo
0f97ac63: hollo
0f9838c4: hpllo
0f98c525: hqllo
0f995186: hrllo
0f99dde7: hsllo
0f9a6a48: htllo
0f9af6a9: hullo
0f9b830a: hvllo
0f9c0f6b: hwllo
0f9c9bcc: hxllo
0f9d27ee: hyll0
0f9d27ef: hyll1
0f9d27f0: hyll2
0f9d27f1: hyll3
0f9d27f2: hyll4
0f9d27f3: hyll5
0f9d27f4: hyll6
0f9d27f5: hyll7
0f9d27f6: hyll8
0f9d282d: hyllo


Obviously the hash code is patterned and these paterns depend heavily on the input string. That is important since in real life we almost always have a house addresses differing in just a single letter or program identifiers, like var1, var2, var3, so such hash wont work with real world data. There is also this Jenkins hash, it is far better and works with real life data, but a bit more expensive and still has patterns recognizable by naked eye without any statistical analyzis. So I have devised my own hash function based on several 8-bit tables. It can be further improved indefinitely by adding more tables:

0fda1cfa: hyll7
1864c82e: hallo
1c2e7fe6: hrllo
1f8f556c: hvllo
23cec7ba: hyll5
365c49df: hyll8
3d6fdff8: hyll2
3fdad270: hcllo
3ffccabb: hello
42ca52e2: hjllo
444f47fc: hpllo
4a5cab6a: hlllo
4a9c241a: hyllo
4e78b60f: hyll3
5542cce3: hbllo
63de5b4f: hullo
6caacdf2: hmllo
7047ee06: hnllo
7f93c530: hqllo
877d5a81: htllo
8929485e: hyll6
8a54f3f8: hfllo
8e648de0: hgllo
9b75886e: hhllo
a5c38ada: hyll1
afd5fcaf: hkllo
c0f0bed4: hyll0
c78518d7: hyll4
d31d4120: hwllo
da87f7c6: hsllo
ee53475f: hdllo
f7d37f32: hillo
fa17acf1: hxllo
fb77afab: hollo



So now I don't have to acknowledge anyone at all, and I can honestly state that I made everything myself. Fuck Communism!

Name: Anonymous 2020-10-06 10:26

>>43
but you stole the music
that's literally communism

Name: Anonymous 2020-10-06 12:23

>>42
Death Giraffe

Name: Anonymous 2020-10-06 12:26

>>43
Why did you test your hash function on input that differs on multiple bytes, but djb's on only one? Is this because you didn't benchmark hashtable performance between the two, and your hash function remains but unproven wibble? (we've all been there.)

Name: Anonymous 2020-10-06 12:50

>>44
No it were Wesnoth team, who stole music from Krondor. I've used creative commons music in the prototype.

Name: Anonymous 2020-10-06 12:55

>>46
What? I've applied both to the same "hello" set word with a few letters changed to demonstrate the shortcomings of simpler hash functions. I've just sorted both outputs to show how the first digits are always the same in djb case, but properly distributed in my personal hash function.

Name: Anonymous 2020-10-06 13:12

>>46

Here is the code
char hell[] = "hello";
for (int i = 'a'; i < 'z'; i++) {
hell[1] = i;
printf("%08x: %s\n", hash_cstr(hell), hell);
}
for (int i = '0'; i < '9'; i++) {
hell[4] = i;
printf("%08x: %s\n", hash_cstr(hell), hell);
}


which was ran as ./a.out | sort


So yeah, even hashing a "hello" properly can lead to issues.

Name: Anonymous 2020-10-06 19:47

Ok. The hashing function I've invented is apparently well known. In fact it is a variation of https://en.wikipedia.org/wiki/Pearson_hashing

Although mine uses several tables - one for each input byte, and doesn't use the hash value itself for lookup since that can reduce the speed a bit. And it also generates only the required number of bits for the power of two hash table, so I don't have to do hascode&table_size

Name: Anonymous 2020-10-10 22:36

Name: Anonymous 2020-10-12 21:29

A few segfauls later
class !CStack;

CStack *CStack.push {}

void test() {
CStack s;
s.push(123).push(456);
}

expands into
CStack *CStack_m_push(CStack *this) {}

void test() {
CStack s;
CStack_m_push(CStack_m_push(&(s),123),456);
}



Note how methods can be called on both pointers and direct values. I.e. this.push(123) would be totally fine.

Name: Anonymous 2020-10-12 21:30

>>52
And the code rewriting this shit is not he most beautiful code around:
sym_t *pg_declof2(cnode_t *n) {
if (!n) return 0;
if (n->id == N_BLOCK) { //for GCC block expressions
return 0;
} else if (n->id == (IDENTIFIER|N_TERM)) {
sym_t *s = lookup(n->text);
if (s) {
return s;
} else {
return 0;
}
} else if (n->id == N_EXPR) {
return 0;
} else if (n->id == N_BEXPR) {
for (; n && n->id==N_BEXPR ; n = n->tail) {
sym_t *decl = pg_declof2(n->head);
if (decl) return decl;
}
if (n) {
return pg_declof2(n);
}
return 0;
} else if (n->id == N_DECL) {
return 0;
} else if (n->id == N_UNARY) {
char c = n->head->text[0];
if (c == '*') pg_declof_ptr_lv--;
else if (c == '&') pg_declof_ptr_lv++;
return pg_declof2(n->tail);
} else if (n->id == N_INDEX) {
pg_declof_ptr_lv--;
return pg_declof2(n->head);
} else if (n->id & N_TERM) {
return 0;
} else if (n->id == N_LIT) {
return 0;
} else if (n->id == N_DOT || n->id == N_ARROW) {
sym_t *l = pg_declof2(n->head);
if (!l) return 0;
char *name = n->tail->text;
char *tname = pg_typename(l->type);
char *mname;
sym_t *s;
int plv = ptr_level(l->decl);
if ((n->id == N_DOT && plv != 1) || (n->id == N_ARROW && plv == 1)) {
mname = sjoin3(tname, "_mf_", name); //field accessor
s = lookup(mname);
free(mname);
if (s) return s;
return 0;
}
mname = sjoin3(tname, "_m_", name);
s = lookup(mname);
free(mname);
if (s) return s;
return 0;
} else if (n->id == N_CALL) {
if (n->head->id != N_DOT) return pg_declof2(n->head);
n = n->head;
sym_t *l = pg_declof2(n->head);
if (!l) return 0;
pg_declof_ptr_lv += ptr_level(l->decl);
char *name = n->tail->text;
char *tname = pg_typename(l->type);
char *mname;
sym_t *s;
mname = sjoin3(tname, "_m_", name);
s = lookup(mname);
free(mname);
if (s) return s;
return 0;
}
return 0;
}

Name: Anonymous 2020-10-12 22:40

Implemented auto keyword. Which make declaration type be the type of its initializer.

Here is the code handling auto vars:
static void pg_decl(cnode_t *n) {
cnode_t *type = n->head;
cnode_t *vars = n->tail;
cnode_t *s = is_struct(type);
if (s) {
pg_struct(s, type, vars);
} else {
indent(); log("vars:\n");
if (type->id==N_TYPE_STOR && type->head->id == (AUTO|N_TERM)) {
cnode_t *expr = vars->head->tail;
sym_t *s = pg_declof(expr);
if (!s) goto normal;
int ptrc = ptr_level(s->decl)+pg_declof_ptr_lv;
if (ptrc < 0) ptrc = 0;
char *tname = pg_typename(s->type);
char *ps = malloc(ptrc+1);
for (int i = 0; i < ptrc; i++) ps[i] = '*';
ps[ptrc] = 0;
char *ts = sjoin(tname,ps);
free(ps);
patch_t *p = new_patch(P_AUTO, n->sofs);
p->as[0].s = ts;
p->as[1].i = type->eofs;
type = s->type;
return;
}
normal:
pg_vars(type, vars);
}
}


It doesn't allow more than one auto var inside single statement, because that is a rewriter, not a true compiler. So all other vars get the type of the first one.

Name: Anonymous 2020-10-13 14:58

>>54
typeof got implemented the same way as auto.

So now I can compile modern C even with the ancient compiler. Think VS 6.0

Although my actual goal is controlling the C language implementation itself, so I could compile Symta on 32bit hardware.

Name: Anonymous 2020-10-13 18:34

Master my anus

Name: Anonymous 2020-10-13 20:33

A thing which can be implemented by rewriting:
f(a,b) {return a+b;}


there the types of a and b can be easily inferred from the first call site, while the return type can be inferred afterwards.

Of course something like
f(a,b) {return f(a,b);}

could never be inferred.

Name: Anonymous 2020-10-13 22:30

>>57
G(a,y) {return f(u,c,k,u);}

Name: Anonymous 2020-10-14 6:58

>>58

Stay mad, Stallman.

Don't change these.
Name: Email:
Entire Thread Thread List