Created
November 1, 2022 16:16
-
-
Save alainlou/f371474eea5eb912e299040adebd5c2d to your computer and use it in GitHub Desktop.
donut.c without any libraries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Original source: https://www.a1k0n.net/2021/01/13/optimizing-donut.html | |
#define UART_ADDR 0x20000000 | |
char b[1760], z[1760]; | |
int mult(int a, int b); | |
int div(int a, int b); | |
int mod(int a, int b); | |
void * memset(void * p, int c, unsigned int n); | |
int print_str(char * c); | |
int putchar(int c); | |
#define R(mul,shift,x,y) \ | |
_=x; \ | |
x -= mult(mul, y)>>shift; \ | |
y += mult(mul, _)>>shift; \ | |
_ = 3145728-mult(x, x)-mult(y, y)>>11; \ | |
x = mult(x, _)>>10; \ | |
y = mult(y, _)>>10; | |
void main() { | |
int sA=1024,cA=0,sB=1024,cB=0,_; | |
for (;;) { | |
memset(b, 32, 1760); // text buffer | |
memset(z, 127, 1760); // z buffer | |
int sj=0, cj=1024; | |
for (int j = 0; j < 90; j++) { | |
int si = 0, ci = 1024; // sine and cosine of angle i | |
for (int i = 0; i < 324; i++) { | |
int R1 = 1, R2 = 2048, K2 = 5120*1024; | |
int x0 = mult(R1, cj) + R2, | |
x1 = mult(ci, x0) >> 10, | |
x2 = mult(cA, sj) >> 10, | |
x3 = mult(si, x0) >> 10, | |
x4 = mult(R1, x2) - (mult(sA, x3) >> 10), | |
x5 = mult(sA, sj) >> 10, | |
x6 = K2 + mult(mult(R1, 1024), x5) + mult(cA, x3), | |
x7 = mult(cj, si) >> 10, | |
x = 40 + div(mult(30, (mult(cB, x1) - mult(sB, x4))), x6), | |
y = 12 + div(mult(15, (mult(cB, x4) + mult(sB, x1))), x6), | |
N = (-mult(cA, x7) - mult(cB, ((-mult(sA, x7)>>10) + x2)) - mult(ci, (mult(cj, sB) >> 10)) >> 10) - x5 >> 7; | |
int o = x + mult(80, y); | |
char zz = (x6-K2)>>15; | |
if (22 > y && y > 0 && x > 0 && 80 > x && zz < z[o]) { | |
z[o] = zz; | |
b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0]; | |
} | |
R(5, 8, ci, si) // rotate i | |
} | |
R(9, 7, cj, sj) // rotate j | |
} | |
for (int k = 0; 1761 > k; k++) | |
putchar(mod(k, 80) ? b[k] : 10); | |
R(5, 7, cA, sA); | |
R(5, 8, cB, sB); | |
print_str("\x1b[23A"); | |
} | |
} | |
int mult(int a, int b) | |
{ | |
int acc = 0; | |
for (int i = 0; i < 32; i++) | |
{ | |
if (a & (1 << i)) | |
acc += b << i; | |
} | |
return acc; | |
} | |
int div(int a, int b) | |
{ | |
int ret = 0; | |
int res_neg = (a < 0) ^ (b < 0); | |
int a_tmp = a < 0 ? -a : a; | |
int b_tmp = b < 0 ? -b : b; | |
while (a_tmp >= b_tmp) | |
{ | |
a_tmp -= b_tmp; | |
ret++; | |
} | |
return res_neg ? -ret : ret; | |
} | |
int mod(int a, int b) | |
{ | |
while (a >= b) | |
{ | |
a -= b; | |
} | |
return a; | |
} | |
void * memset(void * p, int c, unsigned int n) | |
{ | |
for(int i = 0; i < n; i++) | |
{ | |
*((char *)p) = c; | |
p++; | |
} | |
} | |
int print_str(char * s) | |
{ | |
char * p = (char *)UART_ADDR; | |
while (*s != '\0') | |
{ | |
*p = *s; | |
s++; | |
} | |
} | |
int putchar(int c) | |
{ | |
char * p = (char *)UART_ADDR; | |
*p = c; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment