]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/todpic.c
devip: fix arpread, dont return partial entries
[plan9front.git] / sys / src / games / todpic.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <bio.h>
6
7 int wofs;
8 u32int pal[256], bg = 0x00ffff;
9 Biobuf *bp;
10
11 #define abs(x) ((x) < 0 ? -(x) : (x))
12
13 void
14 put8(u8int v)
15 {
16         if(Bwrite(bp, &v, sizeof v) != sizeof v)
17                 sysfatal("put8: short write");
18 }
19
20 void
21 put16(u16int v)
22 {
23         put8(v);
24         put8(v >> 8);
25 }
26
27 void
28 put32(u32int v)
29 {
30         put16(v);
31         put16(v >> 16);
32 }
33
34 int
35 pali(u32int v)
36 {
37         int i, Δ, Δ´;
38         u32int *p;
39
40         i = 0;
41         Δ = abs((char)v - (char)*pal)
42                 + abs((char)(v >> 8) - (char)(*pal >> 8))
43                 + abs((char)(v >> 16) - (char)(*pal >> 16));
44         for(p=pal; p<pal+nelem(pal); p++){
45                 Δ´ = abs((char)v - (char)*p)
46                         + abs((char)(v >> 8) - (char)(*p >> 8))
47                         + abs((char)(v >> 16) - (char)(*p >> 16));
48                 if(Δ´ < Δ){
49                         Δ = Δ´;
50                         i = p - pal;
51                         if(Δ == 0)
52                                 break;
53                 }
54         }
55         return i;
56 }
57
58 void
59 topic(Memimage *i)
60 {
61         int w, h, dx, dy;
62         uchar *np, *b, *buf, *p, *pp;
63         u32int v;
64
65         p = i->data->bdata;
66         dx = Dx(i->r);
67         dy = Dy(i->r);
68         if(dy > 254)
69                 sysfatal("topic: invalid pic height");
70         put16(dx);
71         put16(dy);
72         put16(wofs ? dx / 2 - 1 : i->r.min.x);
73         put16(wofs ? dy - 5 : i->r.min.y);
74         if(i->r.min.x != 0)
75                 dx = i->width;
76         buf = mallocz((5 * dy / 2 + 5) * dx, 1);
77         if(buf == nil)
78                 sysfatal("mallocz: %r");
79         for(w=dx, b=buf; w>0; w--, p+=3){
80                 put32(b - buf + 8 + dx * 4);
81                 for(h=0, np=b+1, pp=p; h<dy; h++, pp+=dx*3){
82                         v = pp[2] << 16 | pp[1] << 8 | pp[0];
83                         if(v == bg){
84                                 if(b - np - 2 > 0){
85                                         *np = b - np - 2;
86                                         *b++ = 0;
87                                         np = b + 1;
88                                 }
89                                 continue;
90                         }
91                         if(b - np - 2 < 0){
92                                 *b++ = h;
93                                 b++;
94                                 *b++ = 0;
95                         }
96                         *b++ = pali(v);
97                 }
98                 if(b - np - 2 >= 0){
99                         *np = b - np - 2;
100                         *b++ = 0;
101                 }
102                 *b++ = 0xff;
103         }
104         Bwrite(bp, buf, b - buf);
105         free(buf);
106 }
107
108 void
109 toflat(Memimage *i)
110 {
111         int n;
112         uchar *p;
113
114         if(Dx(i->r) != 64 || Dy(i->r) != 64)
115                 sysfatal("toflat: invalid flatpic dimensions");
116         p = i->data->bdata;
117         n = 64*64;
118         while(n-- > 0){
119                 put8(pali(p[2] << 16 | p[1] << 8 | p[0]));
120                 p += 4;
121         }
122 }
123
124 static Memimage*
125 iconv(Memimage *i)
126 {
127         Memimage *ni;
128
129         if(i->chan == RGB24)
130                 return i;
131         if((ni = allocmemimage(i->r, RGB24)) == nil)
132                 sysfatal("allocmemimage: %r");
133         memimagedraw(ni, ni->r, i, i->r.min, nil, i->r.min, S);
134         freememimage(i);
135         return ni;
136 }
137
138 void
139 getpal(char *f)
140 {
141         uchar u[3];
142         u32int *p;
143         Biobuf *bp;
144
145         if((bp = Bopen(f, OREAD)) == nil)
146                 sysfatal("getpal: %r");
147         for(p=pal; p<pal+nelem(pal); p++){
148                 if(Bread(bp, u, 3) != 3)
149                         sysfatal("getpal: short read: %r");
150                 *p = u[0]<<16 | u[1]<<8 | u[2];
151         }
152         Bterm(bp);
153 }
154
155 void
156 usage(void)
157 {
158         fprint(2, "usage: %s [-fw] [-b bgcol] [-p palette] [image]\n", argv0);
159         exits("usage");
160 }
161
162 void
163 main(int argc, char **argv)
164 {
165         int fd, flat;
166         char *p;
167         Memimage *i;
168
169         fd = 0;
170         flat = 0;
171         p = "/mnt/wad/playpal";
172         ARGBEGIN{
173         case 'b': bg = strtoul(EARGF(usage()), nil, 0); break;
174         case 'f': flat = 1; break;
175         case 'p': p = EARGF(usage()); break;
176         case 'w': wofs = 1; break;
177         default: usage();
178         }ARGEND
179         if(*argv != nil)
180                 if((fd = open(*argv, OREAD)) < 0)
181                         sysfatal("open: %r");
182         getpal(p);
183         if((bp = Bfdopen(1, OWRITE)) == nil)
184                 sysfatal("Bfdopen: %r");
185         memimageinit();
186         if((i = readmemimage(fd)) == nil)
187                 sysfatal("readmemimage: %r");
188         (flat ? toflat : topic)(iconv(i));
189         exits(nil);
190 }