Merge pull request #1637 from xexyl/endoh114
This commit is contained in:
11 files changed
+310
-85
No files matched your search
@@ -1,2 +1,3 @@
|
||||
prog
|
||||
prog.alt
|
||||
prog.orig
|
||||
@@ -115,8 +115,8 @@ OBJ= ${PROG}.o
|
||||
DATA=
|
||||
TARGET= ${PROG}
|
||||
#
|
||||
ALT_OBJ=
|
||||
ALT_TARGET=
|
||||
ALT_OBJ= ${PROG}.alt.o
|
||||
ALT_TARGET= ${PROG}.alt
|
||||
|
||||
|
||||
#################
|
||||
|
||||
+74
-19
@@ -4,6 +4,10 @@
|
||||
make
|
||||
```
|
||||
|
||||
There is alternate code that lets you redefine the port to bind to, in case
|
||||
there is a firewall issue, and also lets you redefine the timing constant,
|
||||
`STARDATE`. See [Alternate code](#alternate code) below.
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
@@ -40,6 +44,37 @@ But there's more! Try opening in a browser the same address and then see what
|
||||
happens. This is explained by the authors when explaining their inspiration.
|
||||
|
||||
|
||||
## Alternate code:
|
||||
|
||||
This version allows you to redefine the port to bind to, should 1701 be a
|
||||
problem for some reason, and it also allows you to change the timing as
|
||||
described by the author. See [configuration](#configuration) below.
|
||||
|
||||
|
||||
### Alternate build:
|
||||
|
||||
To specify the port to say, 31337, try:
|
||||
|
||||
```sh
|
||||
make clobber CDEFINE="-DNCC=31337" alt
|
||||
```
|
||||
|
||||
To change the `STARDATE` timing constant, try:
|
||||
|
||||
```sh
|
||||
make clobber CDEFINE="-DSTARDATE=5000000" alt
|
||||
```
|
||||
|
||||
You can combine them both of course.
|
||||
|
||||
|
||||
### Alternate use:
|
||||
|
||||
|
||||
Use `prog.alt` as you would `prog` above. Remember that ports < 1024 are
|
||||
privileged ports that unprivileged users cannot use.
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
Port 1701? Well this is not the l2f registered TCP/1701 protocol.
|
||||
@@ -59,7 +94,7 @@ obfuscation awaits the reader of the source!
|
||||
### Abstract
|
||||
|
||||
When launched in web server mode, this application appears to deliver nothing
|
||||
more than a static HTML page. But, in actuality, it provides covert file
|
||||
more than a static HTML page. But, in actuality, it allows covert file
|
||||
transfer over the Internet. This is demonstrated by starting the application as
|
||||
a client-side downloader. The hidden transmitted data cannot be reconstructed
|
||||
or even detected from the binary content of the traffic between the client and
|
||||
@@ -96,10 +131,12 @@ approximately 1 baud.
|
||||
The client-side downloader will automatically terminate if the web server is
|
||||
bounced.
|
||||
|
||||
|
||||
### HTML content
|
||||
|
||||
Plug the URL into a browser to view a static HTML page containing ASCII artwork.
|
||||
|
||||
|
||||
### Exploration
|
||||
|
||||
Studying the network traffic will reveal that the HTML content is static and
|
||||
@@ -111,35 +148,50 @@ mentioned in the abstract, the data is not transmitted within the binary content
|
||||
communicated between the client and the server. A full explanation of the
|
||||
protocol appears below, but feel free to explore before reading further.
|
||||
|
||||
|
||||
### Inspiration
|
||||
|
||||
The inspiration for this program comes from _Star Trek VI: The Undiscovered
|
||||
Country_, specifically the final confrontation between the _Enterprise_ and the
|
||||
enhanced prototype Klingon Bird of Prey. The definitive feature of the
|
||||
prototype was its ability to fire while cloaked. But, perhaps even more
|
||||
impressive was its ability to keep an open communication channel with the
|
||||
_Enterprise_ throughout the battle, enabling the antagonist Chang to taunt
|
||||
Captain Kirk with Shakespearian quotes while he slowly pelted his ship with
|
||||
torpedoes. Normally, cloaked vessels must maintain silent running to avoid
|
||||
detection.
|
||||
The inspiration for this program comes from [Star Trek VI: The Undiscovered
|
||||
Country](https://memory-alpha.fandom.com/wiki/Star_Trek_VI:_The_Undiscovered_Country),
|
||||
specifically the final confrontation between the
|
||||
[Enterprise](https://memory-alpha.fandom.com/wiki/USS_Enterprise_(NCC-1701)) and
|
||||
the enhanced prototype [Klingon Bird of
|
||||
Prey](https://memory-alpha.fandom.com/wiki/Klingon_Bird-of-Prey). The definitive
|
||||
feature of the prototype was its ability to fire while cloaked. But, perhaps
|
||||
even more impressive was its ability to keep an open communication channel with
|
||||
the Enterprise throughout the battle, enabling the antagonist
|
||||
[Chang](https://memory-alpha.fandom.com/wiki/Chang_(General)) to taunt [Captain
|
||||
Kirk](https://memory-alpha.fandom.com/wiki/James_T._Kirk) with
|
||||
[Shakespearian](https://en.wikipedia.org/wiki/William_Shakespeare) quotes while
|
||||
he slowly pelted his ship with torpedoes. Normally, cloaked vessels must
|
||||
maintain silent running to avoid detection.
|
||||
|
||||
The battle is commemorated in the form of ASCII artwork depicting the ships
|
||||
faced head-to-head in the page delivered by the web server. Plus, the program
|
||||
source code is formatted in the shape of a Klingon Bird of Prey. The code
|
||||
itself includes a number of Star Trek references: the registry number of the
|
||||
_Enterprise_ (NCC-1701) is defined as a constant; variable names spell out Cpt.
|
||||
James T. Kirk and Odo (the Deep Space 9 character was played by René Auberjonois
|
||||
who also appeared as Colonel West in _Star Trek VI_); the `STARDATE` constant
|
||||
makes timing configurable; and, the constant `k` stands for Khan (in the final
|
||||
engagement in _Star Trek II: The Wrath of Khan_, the damaged _Enterprise_
|
||||
managed to disable the USS _Reliant_’s shield generator by accessing its prefix
|
||||
code: 16309).
|
||||
Enterprise (NCC-1701) is defined as a constant; variable names spell out Cpt.
|
||||
James T. Kirk and [Odo](https://memory-alpha.fandom.com/wiki/Odo) (the [Deep
|
||||
Space 9](https://memory-alpha.fandom.com/wiki/Star_Trek:_Deep_Space_Nine)
|
||||
character was played by René Auberjonois who also appeared as [Colonel
|
||||
West](https://memory-alpha.fandom.com/wiki/West) in [Star Trek
|
||||
VI](https://memory-alpha.fandom.com/wiki/Star_Trek_VI:_The_Undiscovered_Country));
|
||||
the `STARDATE` constant makes timing configurable; and, the constant `k` stands
|
||||
for [Khan](https://memory-alpha.fandom.com/wiki/Khan_Noonien_Singh) (in the
|
||||
final engagement in [Star Trek II: The Wrath of
|
||||
Khan](https://memory-alpha.fandom.com/wiki/Star_Trek_II:_The_Wrath_of_Khan), the
|
||||
damaged Enterprise managed to disable the USS
|
||||
[Reliant](https://memory-alpha.fandom.com/wiki/USS_Reliant_(NCC-1864))'s shield
|
||||
generator by accessing its prefix code: 16309).
|
||||
|
||||
|
||||
### Secondary size limit
|
||||
|
||||
As obligated by a program that employs 23rd century cloaking technology, when
|
||||
the source is fed as input to IOCCC size tool version 2014-09-23-v19, and the
|
||||
`-i` command line option is used, the value printed is 0.
|
||||
the source is fed as input to [IOCCC size tool version
|
||||
2014-09-23-v19](../iocccsize.c), and the `-i` command line option is used, the
|
||||
value printed is 0.
|
||||
|
||||
|
||||
### Transmission protocol revealed
|
||||
|
||||
@@ -163,6 +215,7 @@ the assumption that the bit value does not affect transmission time.
|
||||
The server relies on the cookie to identify each client uniquely, enabling it to
|
||||
transfer the sequence independently to each client.
|
||||
|
||||
|
||||
### Configuration
|
||||
|
||||
As with all network communication, accurate transmission of data relies on the
|
||||
@@ -174,6 +227,7 @@ faster and less reliably.
|
||||
|
||||
The NCC constant is the web server port number.
|
||||
|
||||
|
||||
### Obfuscations
|
||||
|
||||
* The ASCII artwork is compressed using run-length encoding.
|
||||
@@ -187,6 +241,7 @@ referenced via pointers.
|
||||
* Standard constants and ASCII characters were replaced with their respective
|
||||
numerical values.
|
||||
|
||||
|
||||
### Compiler warnings
|
||||
|
||||
For space considerations, the following include statements were dropped
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/**??/
|
||||
/
|
||||
#include<netdb.h>
|
||||
#include<stdio.h>
|
||||
#include<sys/time.h>
|
||||
#ifndef NCC
|
||||
#define NCC 1701
|
||||
#endif
|
||||
#ifndef STARDATE
|
||||
#define STARDATE 500000
|
||||
#endif
|
||||
#define k 16309
|
||||
|
||||
int C,p,t,J,a,m,e,s,T,K,i,r[k],_[k][2],c[k][2],f=NCC;
|
||||
fd_set O,d,o;char g[8][k],*h,j[]="0\1&me\1&t&e\1TFTTJPO>"
|
||||
"\1&t\\_<\16\v^\1&+\\_;^&o;&e\1TFU.DPPLJF;\1iuuq;00&92:2\\_0^&"
|
||||
"o\1&tDppljf;!tfttjpo>&t\16\v\16\v\1HFU!&t!IUUQ02/1\16\vIptu;!"""
|
||||
"&t\16\v\1IUUQ02/1!311!PL\16\vDpoufou.uzqf;!ufyu0iunm\16\vFyqjsft;!1"""
|
||||
"\16\vTfu.Dppljf;!tfttjpo>&t\16\vDpoufou.Mfohui;!&me\16\v\16\v&t\1=iunm?=c" "pez!chdpmps>#cmbdl"
|
||||
"#?=ejw!tuzmf>(qptjujpo;bctpmvuf<upq;61&&<mfgu;61&&<usbotgpsn;usbotmbufY).61&&*u" "sbotmbufZ).61&&*<(?=gpou!dpm"
|
||||
"ps>#xijuf#?=qsf?&t=0qsf?=0gpou?=0ejw?=0cpez?=0iunm?\1T`K!`.`[!G!G`\v]C`)K>0`>`0!E`/" "D.(D.aD./E`D!C`p`K!F`0F`}\vM!]`!]E!"
|
||||
"]E./J`/E.0C!G>I`0L.0\vO!]!]D!0C!0E!a.`.(K!)E`0I!]G`E!}\vK!C`-C.a/a.(//(.`[!N!]C!+!]\vJ!0E`K!}}[!K!C`0E`0C`\vO!aC./E`-.([!K!|K`|";struct sockad\
|
||||
dr_in l;struct timeval n,q;struct hostent*u;long w;void x(int y){close(y);FD_CLR(y,&O);if(y>=m)while(--m)if(FD_ISSET(m,&O))break;}vo\
|
||||
id z(char*A,char*B){char*D,*E=A,*F=A;for(0[0[g]]=0;*E;E++)if(*E==10){if(E-F==(*(E-1)-13?1:2))break;*E=0;if(!strncmp(F,B,strlen(B))&&(D=strstr(F,j+\
|
||||
11))){sscanf(D+8,j+20,0[g]);break;}F=E+1;}else*E=toupper(*E);}int main(int G,char**H){h=j;while(*h)(*h)--,h++;h=j+414;do{t=*h++;e=1;if(t>=65&&t<=90)e
|
||||
=t-64,t=*h++;while(e--)6[g][i++]=t;}while(t);sprintf(7[g],j+229,6[g]);l.sin_family=2;if(G>1){sscanf(1[H],j+53,4[g],&K);sprintf(2[g],j+97,*(1[H]+K)?1[
|
||||
H]+K:j,4[g]);sscanf(4[g],j+29,&i,&f);i[4[g]]=0;u=gethostbyname(4[g]);memcpy(&l.sin_addr.s_addr,0[u->h_addr_list],u->h_length);l.sin_port=htons(f);\
|
||||
for(;;close(G))if(!connect(G=socket(2,1,0),&l,sizeof l))for(;;){strcpy(1[g],0[g]);s=sprintf(5[g],j+72,2[g],0[g]);if(write(G,5[g],s)<0)break;gett\
|
||||
imeofday(&n,0);0[3[g]]=0;e=read(G,3[g],k);if(e<0)break;else if(e&&*3[g]==72){gettimeofday(&q,0);3[g][k-1]=0;z(3[g],j+41);if(0[1[g]])if(!strnc\
|
||||
mp(1[g],0[g],strlen(1[g]))){t=0;if((q.tv_sec-n.tv_sec)*1000000+q.tv_usec-n.
|
||||
tv_usec<STARDATE-1000){t=p<15?1:16;p+=t;C+=t;}else p=p<15?15:255;if(p==2\
|
||||
55){putchar(C);fflush(stdout);C=p=0;}}else{T=1;goto l;}}}}else{for(f=0;
|
||||
f<k;f++){if((i=fgetc(stdin))<0)break;f[r]=i;}for(i=0;i<k;i++){0[i[_]]
|
||||
=1[i[_]]=-1;0[i[c]]=1[i[c]]=0;}gettimeofday(&n,0);p=sprintf(5[g],j+2
|
||||
,n.tv_sec);n.tv_sec=0;n.tv_usec=STARDATE;FD_ZERO(&d);FD_ZERO(&O);F\
|
||||
D_ZERO(&o);l.sin_addr.s_addr=0;l.sin_port=htons(NCC);bind(G=sock\
|
||||
et(2,1,0),&l,sizeof l);listen(G,10);FD_SET(m=G,&O);for(i=1,t=0;;
|
||||
){d=O;C=select(m+1,&d,0,0,0);if(C<=0){if(!i&&t)x(t);goto l;}fo\
|
||||
r(J=t;C&&J<=m;J++)if(FD_ISSET(J,&d)){C--;if(J==G){t=accept(G,
|
||||
0,0);FD_SET(t,&O);FD_CLR(t,&d);FD_SET(t,&o);if(t>m)m=t;t=0;
|
||||
}else if(!i||FD_ISSET(J,&o)){e=read(J,2[g],k);K=0;if(e>0){
|
||||
2[g][k-1]=0;if(*2[g]==71){a=0;strcpy(1[g],0[g]);z(2[g],j+
|
||||
45);if(!strncmp(0[g],5[g],strlen(5[g]))&&!strncmp(1[g],
|
||||
0[g],strlen(1[g]))){K=atoi(0[g]+p);}if(K){if(0[K[_]]<f
|
||||
){if(a=(1[K[_]]<15?1[K[_]]:1[K[_]]>>4)>=(1[K[_]]<15?
|
||||
0[K[_]][r]&15:0[K[_]][r]>>4))1[K[_]]=1[K[_]]<15?1\
|
||||
5:255;else 1[K[_]]+=1[K[_]]<16?1:16;if(_[K][1]==\
|
||||
255){0[K[_]]++;1[K[_]]=0;}}else{write(1[K[c]],_[
|
||||
K],sizeof(_[K]));close(1[K[c]]);K=0;}}else fo\
|
||||
r(s=1;s<k;s++)if(0[s[_]]==-1){0[s[_]]=1[s[_]]
|
||||
=0;K=s;break;}if(K)sprintf(0[g],j+6,5[g],K)
|
||||
;else 0[0[g]]=0;w=sprintf(3[g],j+125,0[g],
|
||||
strlen(7[g]),7[g]);if(i){pipe(c[K]);if(!
|
||||
(i=fork())){close(0[K[c]]);FD_ZERO(&O);
|
||||
FD_SET(t=m=J,&O);}}if(i<0){T=1;goto l;
|
||||
}if(i){close(1[K[c]]);FD_SET(0[K[c]]
|
||||
,&O);if(0[K[c]]>m)m=0[K[c]];x(J);\
|
||||
break;}else{if(a){n.tv_sec=0;n.t\
|
||||
v_usec=STARDATE;select(0,0,0,0,&
|
||||
n);}write(J,3[g],w);if(!K){close(J);return 0;}}}}else if(i){
|
||||
close(J);FD_CLR(J,&o);x(J);}else{write(1[K[c]],K[_],sizeof(K[_
|
||||
]));close(1[K[c]]);close(J);return 0;}}else{for(K=0;K<=m;K++)if(
|
||||
0[K[c]]==J){read(J,K[_],sizeof(K[_]));x(J);if(_[K][0]>=f){0[K[_]
|
||||
]=1[K[_]]=-1;0[K[c]]=1[K[c]]=0;}break;}}}}}l:close(G);return T;}
|
||||
+26
-7
@@ -5,7 +5,9 @@ make
|
||||
```
|
||||
|
||||
There is an alternate version that the author provided but fixed in 2023 to
|
||||
compile. See [alternate code](#alternate-code) below.
|
||||
compile with modern systems and to allow one to reconfigure the constants `X1`,
|
||||
`X2`, `Y1` and `Y2` (which were magic numbers). See [Alternate
|
||||
code](#alternate-code) below.
|
||||
|
||||
|
||||
## To use:
|
||||
@@ -29,16 +31,30 @@ various regions of the fractal.
|
||||
|
||||
The alternate code is included as [prog.alt.c](prog.alt.c) so you can more
|
||||
easily see the difference in what it might look like if the C was more
|
||||
recognisable. To use, try:
|
||||
recognisable and also to let you reconfigure the coordinates.
|
||||
|
||||
|
||||
### Alternate build:
|
||||
|
||||
```sh
|
||||
make alt
|
||||
```
|
||||
|
||||
Use `prog.alt` as you would `prog`.
|
||||
If you wish to redefine the coordinates you can do so by defining `X1`, `X2`,
|
||||
`Y1` and/or `Y2`, which default to: `-2`, `1`, `-1.3` and `1.3` respectively.
|
||||
For instance:
|
||||
|
||||
Bonus: the author explains how to configure the program but can you figure out
|
||||
how to do it in the alternate code?
|
||||
|
||||
```sh
|
||||
make clobber CDEFINE="-DX1=-3 -DX2=2 -DY1=-2.3 -DY2=2.3" alt
|
||||
```
|
||||
|
||||
You may pick and choose which ones to redefine.
|
||||
|
||||
|
||||
### Alternate use:
|
||||
|
||||
Use `prog.alt` as you would `prog`.
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
@@ -51,19 +67,21 @@ We liked the use of unary notation facilitated by variadic macros.
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
|
||||
### Portability
|
||||
|
||||
The application was written on a standard Ubuntu 14.04 and tested with
|
||||
gcc 4.9.1 and clang 3.5 on 64 bit system (though this should not matter).
|
||||
gcc 4.9.1 and clang 3.5 on a 64 bit system (though this should not matter).
|
||||
The application makes no assumption regarding any system specific settings,
|
||||
and it only needs a console to run. The provided Makefile is just to have
|
||||
an easy compilation. I don't see any problems porting it to different
|
||||
compiler/system as long as it supports the C99 standard.
|
||||
|
||||
|
||||
### The application
|
||||
|
||||
The purpose of the application is mainly to illustrate the weird possibilities
|
||||
of the C preprocessor, than to be a full featured console mode Mandelbrot
|
||||
of the C preprocessor, rather than to be a full featured console mode Mandelbrot
|
||||
drawer. There are tools much better suited for drawing fractals.
|
||||
|
||||
The usage of recognizable elements from the C programming language in the
|
||||
@@ -98,6 +116,7 @@ is to modify the source code at the indicated location: the line
|
||||
that the adventurous programmer can manually modify the coordinates of the
|
||||
fractal to be drawn on the screen.
|
||||
|
||||
|
||||
### Compiler warnings
|
||||
|
||||
Yes, unfortunately there are compiler warnings of the kind "initialization makes
|
||||
|
||||
+14
-2
@@ -1,6 +1,18 @@
|
||||
#include <stdio.h>
|
||||
double _[]={-2
|
||||
,1,-1.3 ,1.3, 0, 0,0,0
|
||||
#ifndef X1
|
||||
#define X1 -2
|
||||
#endif
|
||||
#ifndef X2
|
||||
#define X2 1
|
||||
#endif
|
||||
#ifndef Y1
|
||||
#define Y1 -1.3
|
||||
#endif
|
||||
#ifndef Y2
|
||||
#define Y2 1.3
|
||||
#endif
|
||||
double _[]={X1
|
||||
,X2,Y1 ,Y2, 0, 0,0,0
|
||||
,0 ,0,50, 80, 0,0,0 ,255
|
||||
, 8,0}; int main (
|
||||
int j) {if (j== 1 ){ if(
|
||||
|
||||
+13
-18
@@ -15,25 +15,18 @@ make
|
||||
### Try:
|
||||
|
||||
```sh
|
||||
./prog > main.c
|
||||
|
||||
make main
|
||||
./main Hello
|
||||
./try.sh
|
||||
```
|
||||
|
||||
Also try:
|
||||
|
||||
```sh
|
||||
make rake
|
||||
```
|
||||
|
||||
which will run the [rake.sh](rake.sh) script and then `prog` if all is built
|
||||
okay. If `rake` is not installed then it will check that `gem` is installed. If
|
||||
`gem` is not installed it will tell you where to get it and then tell you how to
|
||||
install `rake`. Otherwise, if `rake` is installed it will try running `rake `
|
||||
and if that fails to run it will tell you to run a `gem` command as either root
|
||||
or via sudo and then to try running `make rake` or `./rake.sh` again. If `rake`
|
||||
succeeds it will run `./prog` which can be used to build `main.c`.
|
||||
The script will ask you if you wish to run `make rake` but this is not necessary
|
||||
to fully enjoy the entry. `make rake` will run the [rake.sh](rake.sh) script and
|
||||
then `prog` if all is built okay. If `rake` is not installed then it will check
|
||||
that `gem` is installed. If `gem` is not installed it will tell you where to get
|
||||
it and then tell you how to install `rake`. Otherwise, if `rake` is installed it
|
||||
will try running `rake ` and if that fails to run it will tell you to run a
|
||||
`gem` command as either root or via sudo and then to try running `make rake` or
|
||||
`./rake.sh` again. If `rake` succeeds it will run `./prog` which can be used to
|
||||
build `main.c`.
|
||||
|
||||
What is the difference between running `./prog` and `main`?
|
||||
|
||||
@@ -64,9 +57,11 @@ more than 1000 words.
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
|
||||
### Remarks
|
||||
|
||||
You may want to use a large display with a very small-font terminal.
|
||||
You may want to use a large display with a very small terminal font.
|
||||
|
||||
|
||||
### Spoiler
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ if ! type -P rake >/dev/null 2>&1; then
|
||||
else
|
||||
echo "Please run the following command as root or via sudo:" 1>&2
|
||||
echo ""
|
||||
echo " gem install rake" 1>2
|
||||
echo " gem install rake" 1>&2
|
||||
echo "" 1>&2
|
||||
echo "and then try running make rake or running $0 again" 1>&2
|
||||
fi
|
||||
|
||||
+29
-20
@@ -7,8 +7,8 @@ requires a bit stream, Reed-Solomon codes, BCH codes, data relocation, big (and
|
||||
irregular!) numerical tables, human-oriented pattern arrangement (difficult to
|
||||
implement by a small program), etc.
|
||||
|
||||
On the other hand, a quine has a big restriction:
|
||||
it needs to have two copies of the program!
|
||||
On the other hand, a quine has a big restriction: it needs to have two copies of
|
||||
the program!
|
||||
|
||||
Do you think that it is possible to write QR code encoder in C within *1kB*?
|
||||
|
||||
@@ -18,7 +18,9 @@ Do you think that it is possible to write QR code encoder in C within *1kB*?
|
||||
It is known that we can mitigate the quine restriction by `eval`.
|
||||
For example, this is a quine written in Ruby:
|
||||
|
||||
eval s="print 'eval s='; p s"
|
||||
```ruby
|
||||
eval s="print 'eval s='; p s"
|
||||
```
|
||||
|
||||
Note that `print` appears just once in the program.
|
||||
|
||||
@@ -29,8 +31,10 @@ char s[]="<main code>int main() { <VM code> }";
|
||||
int main() { <VM code>; }
|
||||
```
|
||||
|
||||
* `<VM code>` : An own VM implementation (written in C) that executes the main code
|
||||
* `<main code>` : An object code of quine and QR code encoder (written in the assembly language of the VM)
|
||||
* `<VM code>` : An own VM implementation (written in C) that executes the main
|
||||
code.
|
||||
* `<main code>` : An object code of quine and QR code encoder (written in the
|
||||
assembly language of the VM).
|
||||
|
||||
`<main code>` (about 1100 bytes) appears once and `<VM code>` (about 450 bytes)
|
||||
appears twice. So the whole code is about 1100 + 450 * 2 = 2000 bytes. Hooray!
|
||||
@@ -45,7 +49,7 @@ code>` and `<VM code>`.
|
||||
* 21 integer registers access
|
||||
* read, write, inc-and-read, dec-and-read
|
||||
* Binary operations
|
||||
* add, sub, mul, div, mod, xor, less than, equal, rshift
|
||||
* add, sub, mul, div, mod, xor, less than, equal, right shift
|
||||
* Stack operation
|
||||
* push (an immediate value)
|
||||
* Heap access
|
||||
@@ -55,10 +59,11 @@ code>` and `<VM code>`.
|
||||
* Misc.
|
||||
* putchar, exit
|
||||
|
||||
The instructions have variable length, but many of them are represented as one
|
||||
printable character. (See `machine.rb` and `assemble.rb` in detail.) The
|
||||
mapping between instructions and characters is also carefully designed to
|
||||
minimize `<VM code>`, which makes the resulted program non-human-readable.
|
||||
The instructions have variable lengths, but many of them are represented as one
|
||||
printable character. (See [machine.rb](machine.rb) and
|
||||
[assemble.rb](assemble.rb) in detail.) The mapping between instructions and
|
||||
characters is also carefully designed to minimize `<VM code>`, which makes the
|
||||
resulted program non-human-readable.
|
||||
|
||||
|
||||
## How did I create the main code?
|
||||
@@ -126,30 +131,34 @@ $ rake
|
||||
|
||||
I checked that the following QR code readers can read the output of my program.
|
||||
|
||||
* Linux: [ZBar bar code reader][1]
|
||||
* Linux: [ZBar bar code reader][1].
|
||||
|
||||
### 2023 note from the judges:
|
||||
|
||||
The author also tested an Android app called Barcode Scanner] which used to be
|
||||
### A note from the judges in 2023:
|
||||
|
||||
The author also tested an Android app called Barcode Scanner which used to be
|
||||
found at
|
||||
`https://play.google.com/store/apps/details?id=com.google.zxing.client.android`
|
||||
but it appears to no longer exist.
|
||||
|
||||
[1]: http://zbar.sourceforge.net/
|
||||
|
||||
You can use `tool.rb` to convert the output to a png file.
|
||||
You can use [tool.rb](tool.rb) to convert the output to a png file.
|
||||
|
||||
$ ./main Hello | ruby tool.rb > hello.png
|
||||
```sh
|
||||
./main Hello | ruby tool.rb > hello.png
|
||||
|
||||
$ zbarimg -q hello.png
|
||||
QR-Code:Hello
|
||||
$ zbarimg -q hello.png
|
||||
QR-Code:Hello
|
||||
|
||||
$ ruby tool.rb prog.c
|
||||
$ ruby tool.rb prog.c | ruby tool.rb
|
||||
```
|
||||
|
||||
$ ruby tool.rb prog.c
|
||||
$ ruby tool.rb prog.c | ruby tool.rb
|
||||
|
||||
## Limitations
|
||||
|
||||
* QR code error correction level is fixed to L (Low).
|
||||
* It supports only byte mode (not numeric, alphanumeric, kanji mode...)
|
||||
* It supports only byte mode (not numeric, alphanumeric, kanji mode...).
|
||||
* The mask pattern is fixed to 4.
|
||||
* The mask is not applied to the remained bits.
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate IOCCC winner 2014/endoh1
|
||||
#
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy
|
||||
# way.
|
||||
if [[ -z "$CC" ]]; then
|
||||
CC="cc"
|
||||
fi
|
||||
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# clear screen after compilation so that only the entry is shown
|
||||
clear
|
||||
|
||||
read -r -n 1 -p "Press any key to show prog.c (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
less -EXF prog.c
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog: "
|
||||
echo 1>&2
|
||||
./prog
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog > main.c: "
|
||||
echo 1>&2
|
||||
./prog > main.c
|
||||
read -r -n 1 -p "Press any key to run: make main: "
|
||||
echo 1>&2
|
||||
make main
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./main IOCCC: "
|
||||
echo 1>&2
|
||||
./main IOCCC
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./main Hello: "
|
||||
echo 1>&2
|
||||
./main Hello
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog IOCCC: "
|
||||
echo 1>&2
|
||||
./prog IOCCC
|
||||
|
||||
echo 1>&2
|
||||
|
||||
read -r -p "Do you want to run make rake (Y/N)? "
|
||||
if [[ "$REPLY" == "y" || "$REPLY" == "Y" ]]; then
|
||||
make rake 2>/dev/null
|
||||
fi
|
||||
+32
-16
@@ -3658,35 +3658,51 @@ implicitly (Linux doesn't seem to but macOS does).
|
||||
# <a name="2014"></a>2014
|
||||
|
||||
|
||||
## [2014/birken](2014/birken/prog.c) ([README.md](2014/birken/README.md))
|
||||
|
||||
[Cody](#cody) provided the [alternate
|
||||
code](2014/birken/README.md#alternate-code) that lets one redefine the port to
|
||||
bind to in case there is a firewall issue or there is some other reason to not
|
||||
have the default port. Remember that ports < 1024 are privileged. It also lets
|
||||
you redefine the timing constant `STARDATE` (see the author's remarks for more
|
||||
details).
|
||||
|
||||
|
||||
## [2014/deak](2014/deak/prog.c) ([README.md](2014/deak/README.md))
|
||||
|
||||
[Cody](#cody) fixed the code that the author provided which would be what the program
|
||||
would look like if, as the author put it:
|
||||
[Cody](#cody) added [alt code](2014/deak/README.md#alternate-code) that lets one
|
||||
reconfigure the coordinates but instead of being a modified version of the entry
|
||||
it is the version the author provided which would be what the program would look
|
||||
like if, as the author put it:
|
||||
|
||||
> The usage of recognizable elements from the C programming language in the
|
||||
application source code is intentionally kept to a bare minimum. If this phrase
|
||||
would not be true, the application would be the following:
|
||||
application source code is intentionally kept to a bare minimum.
|
||||
|
||||
It did not compile because a value was left off the `return` statement.
|
||||
.. was not true.
|
||||
|
||||
Cody added this as alternate code just for fun and so one can more easily see
|
||||
the difference to really appreciate the obfuscation.
|
||||
This alt version did not originally compile because a value was left off the
|
||||
`return` statement (this might have been fixed in the README.md file too) so
|
||||
that was fixed and it also has `#include <stdio.h>` for `putchar(3)`. The
|
||||
`#ifndef..#define..#endif` was not part of the original alt code, of course.
|
||||
|
||||
|
||||
## [2014/endoh1](2014/endoh1/prog.c) ([README.md](2014/endoh1/README.md]))
|
||||
|
||||
[Cody](#cody) added the [rake.sh](2014/endoh1/rake.sh) script and `make rake` rule that
|
||||
runs the script. This script will check that `rake` is installed and if it is
|
||||
not it will report this and then check that `gem` is installed. It checks that
|
||||
`gem` is installed in this case because `gem` is how you install `rake`. If
|
||||
`gem` is not installed it tells you to get it along with how to install `gem`.
|
||||
Then it tells you how to install `rake`. If `rake` fails to run then it tells
|
||||
you to install a specific gem and then to try again. Finally if `rake` succeeds
|
||||
it will verify that `prog` is executable and if it is it will run it.
|
||||
[Cody](#cody) added the [rake.sh](2014/endoh1/rake.sh) script and `make rake`
|
||||
rule that runs the script. This script will check that `rake` is installed and
|
||||
if it is not it will report this and then check that `gem` is installed. It
|
||||
checks that `gem` is installed in this case because `gem` is how you install
|
||||
`rake`. If `gem` is not installed it tells you to get it along with how to
|
||||
install `gem`. Then it tells you how to install `rake`. If `rake` fails to run
|
||||
then it tells you to install a specific gem and then to try again. Finally if
|
||||
`rake` succeeds it will verify that `prog` is executable and if it is it will
|
||||
run it.
|
||||
|
||||
Cody also added the [try.sh](2014/endoh1/try.sh) script.
|
||||
|
||||
**_Barely_** worth noting but done nonetheless, Cody renamed the `read_me.md`
|
||||
file to [spoilers.md](2014/endoh1/spoilers.md) to be clearer in its purpose as
|
||||
it is a file with spoilers.
|
||||
it is a file with spoilers (and too close to README.md?).
|
||||
|
||||
|
||||
## [2014/maffiodo1](2014/maffiodo1/prog.c) ([README.md](2014/maffiodo1/README.md]))
|
||||
|
||||
Reference in new issue
Block a user