1 /* NetHack 3.6	amirip.c	$NHDT-Date: 1450453302 2015/12/18 15:41:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
2 /* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1991,1992,1993,1995,1996.
3  */
4 /* NetHack may be freely redistributed.  See license for details. */
5 
6 #include "hack.h"
7 #include <exec/types.h>
8 #include <exec/io.h>
9 #include <exec/alerts.h>
10 #include <exec/devices.h>
11 #include <devices/console.h>
12 #include <devices/conunit.h>
13 #include <graphics/gfxbase.h>
14 #include <graphics/gfxmacros.h>
15 #include <intuition/intuition.h>
16 #include <libraries/dosextens.h>
17 #include <ctype.h>
18 #include <string.h>
19 #include "winami.h"
20 #include "windefs.h"
21 #include "winext.h"
22 #include "winproto.h"
23 
24 static struct RastPort *rp;
25 
26 #ifdef AMII_GRAPHICS
27 
28 #undef NULL
29 #define NULL 0
30 
31 #ifdef AZTEC_C
32 #include <functions.h>
33 #else
34 #ifdef _DCC
35 #include <clib/dos_protos.h>
36 #include <clib/exec_protos.h>
37 #include <clib/console_protos.h>
38 #include <clib/diskfont_protos.h>
39 #else
40 #include <proto/dos.h>
41 #include <proto/exec.h>
42 #include <proto/console.h>
43 #include <proto/diskfont.h>
44 #endif
45 
46 static char *load_list[] = { "tomb.iff", 0 };
47 static BitMapHeader tomb_bmhd;
48 static struct BitMap *tbmp[1] = { 0 };
49 
50 static int cols[2] = { 154, 319 }; /* X location of center of columns */
51 static int cno = 0; /* current column */
52 #define TEXT_TOP (65 + yoff)
53 
54 static xoff, yoff; /* image centering */
55 
56 /* terrible kludge */
57 /* this is why prototypes should have ONLY types in them! */
58 #undef red
59 #undef green
60 #undef blue
61 #undef index
62 #ifdef _DCC
63 #include <clib/graphics_protos.h>
64 #include <clib/intuition_protos.h>
65 #else
66 #include <proto/graphics.h>
67 #include <proto/intuition.h>
68 #endif
69 #endif /* AZTEC_C */
70 
71 static struct Window *ripwin = 0;
72 static void tomb_text(char *);
73 static void dofade(int, int, int);
74 static int search_cmap(int, int, int);
75 
76 #define STONE_LINE_LEN                 \
77     13 /* # chars that fit on one line \
78         * (note 1 ' ' border) */
79 
80 #define DEATH_LINE 10
81 #define YEAR_LINE 15
82 
83 static unsigned short tomb_line;
84 
85 extern struct amii_DisplayDesc *amiIDisplay;
86 extern struct Screen *HackScreen;
87 extern int havelace;
88 
89 static unsigned short transpalette[AMII_MAXCOLORS] = {
90     0x0000,
91 };
92 
93 static struct NewWindow newwin = { 0, 0, 640, 200, 1, 0,
94                                    MOUSEBUTTONS | VANILLAKEY | NOCAREREFRESH,
95                                    BORDERLESS | ACTIVATE | SMART_REFRESH,
96                                    NULL, NULL, (UBYTE *) NULL, NULL, NULL, -1,
97                                    -1, 0xffff, 0xffff, CUSTOMSCREEN };
98 
99 int wh; /* was local in outrip, but needed for SCALE macro */
100 
101 int cmap_white, cmap_black;
102 
103 void
amii_outrip(tmpwin,how,when)104 amii_outrip(tmpwin, how, when)
105 winid tmpwin;
106 int how;
107 time_t when;
108 {
109     int just_return = 0;
110     int done, rtxth;
111     struct IntuiMessage *imsg;
112     int i;
113     register char *dpx;
114     char buf[200];
115     int line, tw, ww;
116     char *errstr = NULL;
117     long year;
118 
119     if (!WINVERS_AMIV || HackScreen->RastPort.BitMap->Depth < 4)
120         goto cleanup;
121 
122     /* Use the users display size */
123     newwin.Height = amiIDisplay->ypix - newwin.TopEdge;
124     newwin.Width = amiIDisplay->xpix;
125     newwin.Screen = HackScreen;
126 
127     for (i = 0; i < amii_numcolors; ++i)
128         sysflags.amii_curmap[i] = GetRGB4(HackScreen->ViewPort.ColorMap, i);
129 
130     ripwin = OpenWindow((void *) &newwin);
131     if (!ripwin)
132         goto cleanup;
133 
134     LoadRGB4(&HackScreen->ViewPort, transpalette, amii_numcolors);
135 
136     rp = ripwin->RPort;
137     wh = ripwin->Height;
138     ww = ripwin->Width;
139 
140 #ifdef HACKFONT
141     if (HackFont)
142         SetFont(rp, HackFont);
143 #endif
144 
145     tomb_bmhd = ReadImageFiles(load_list, tbmp, &errstr);
146     if (errstr)
147         goto cleanup;
148     if (tomb_bmhd.w > ww || tomb_bmhd.h > wh)
149         goto cleanup;
150 
151 #define GENOFF(full, used) ((((full) - (used)) / 2) & ~7)
152     xoff = GENOFF(ww, tomb_bmhd.w);
153     yoff = GENOFF(wh, tomb_bmhd.h);
154     for (i = 0; i < SIZE(cols); i++)
155         cols[i] += xoff;
156 
157     cmap_white = search_cmap(0, 0, 0);
158     cmap_black = search_cmap(15, 15, 15);
159 
160     BltBitMap(*tbmp, 0, 0, rp->BitMap, xoff, yoff, tomb_bmhd.w, tomb_bmhd.h,
161               0xc0, 0xff, NULL);
162 
163     /* Put together death description */
164     formatkiller(buf, sizeof buf, how, FALSE);
165 
166     tw = TextLength(rp, buf, STONE_LINE_LEN) + 40;
167 
168     {
169         char *p = buf;
170         int x, tmp;
171         for (x = STONE_LINE_LEN; x; x--)
172             *p++ = 'W';
173         *p = '\0';
174         tmp = TextLength(rp, buf, STONE_LINE_LEN) + 40;
175         tw = max(tw, tmp);
176     }
177 
178     /* There are 5 lines of text on the stone. */
179     rtxth = ripwin->RPort->TxHeight * 5;
180 
181     SetAfPt(rp, (UWORD *) NULL, 0);
182     SetDrPt(rp, 0xFFFF);
183 
184     tomb_line = TEXT_TOP;
185 
186     SetDrMd(rp, JAM1);
187 
188     /* Put name on stone */
189     Sprintf(buf, "%s", plname);
190     buf[STONE_LINE_LEN] = 0;
191     tomb_text(buf);
192 
193     /* Put $ on stone */
194     Sprintf(buf, "%ld Au", done_money);
195     buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */
196     tomb_text(buf);
197 
198     /* Put together death description */
199     formatkiller(buf, sizeof buf, how, FALSE);
200 
201     /* Put death type on stone */
202     for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
203         register int i, i0;
204         char tmpchar;
205 
206         if ((i0 = strlen(dpx)) > STONE_LINE_LEN) {
207             for (i = STONE_LINE_LEN; ((i0 > STONE_LINE_LEN) && i); i--) {
208                 if (dpx[i] == ' ')
209                     i0 = i;
210             }
211             if (!i)
212                 i0 = STONE_LINE_LEN;
213         }
214 
215         tmpchar = dpx[i0];
216         dpx[i0] = 0;
217         tomb_text(dpx);
218 
219         if (tmpchar != ' ') {
220             dpx[i0] = tmpchar;
221             dpx = &dpx[i0];
222         } else {
223             dpx = &dpx[i0 + 1];
224         }
225     }
226 
227     /* Put year on stone */
228     year = yyyymmdd(when) / 10000L;
229     Sprintf(buf, "%4ld", year);
230     tomb_text(buf);
231 
232 #ifdef NH320_DEDICATION
233     /* dedication */
234     cno = 1;
235     tomb_line = TEXT_TOP;
236     tomb_text("This release");
237     tomb_text("of NetHack");
238     tomb_text("is dedicated");
239     tomb_text("to the");
240     tomb_text("memory of");
241     tomb_text("");
242     tomb_text("Izchak");
243     tomb_text(" Miller");
244     tomb_text("");
245     tomb_text("1935-1994");
246     tomb_text("");
247     tomb_text("Ascended");
248 #endif
249     /* Fade from black to full color */
250     dofade(0, 16, 1);
251 
252     /* Flush all messages to avoid typeahead */
253     while (imsg = (struct IntuiMessage *) GetMsg(ripwin->UserPort))
254         ReplyMsg((struct Message *) imsg);
255     done = 0;
256     while (!done) {
257         WaitPort(ripwin->UserPort);
258         while (imsg = (struct IntuiMessage *) GetMsg(ripwin->UserPort)) {
259             switch (imsg->Class) {
260             case MOUSEBUTTONS:
261             case VANILLAKEY:
262                 done = 1;
263                 break;
264             }
265             ReplyMsg((struct Message *) imsg);
266         }
267     }
268 
269     /* Fade out */
270     dofade(16, 0, -1);
271     just_return = 1;
272 
273 cleanup:
274     /* free everything */
275     if (ripwin) {
276         Forbid();
277         while (imsg = (struct IntuiMessage *) GetMsg(ripwin->UserPort))
278             ReplyMsg((struct Message *) imsg);
279         CloseWindow(ripwin);
280         Permit();
281     }
282     LoadRGB4(&HackScreen->ViewPort, sysflags.amii_curmap, amii_numcolors);
283 
284     if (tbmp[0])
285         FreeImageFiles(load_list, tbmp);
286     if (just_return)
287         return;
288     /* fall back to the straight-ASCII version */
289     genl_outrip(tmpwin, how, when);
290 }
291 
292 static void
tomb_text(p)293 tomb_text(p)
294 char *p;
295 {
296     char buf[STONE_LINE_LEN * 2];
297     int l;
298 
299     tomb_line += rp->TxHeight;
300 
301     if (!*p)
302         return;
303     sprintf(buf, " %s ", p);
304     l = TextLength(rp, buf, strlen(buf));
305 
306     SetAPen(rp, cmap_white);
307     Move(rp, cols[cno] - (l / 2) - 1, tomb_line);
308     Text(rp, buf, strlen(buf));
309 
310     SetAPen(rp, cmap_white);
311     Move(rp, cols[cno] - (l / 2) + 1, tomb_line);
312     Text(rp, buf, strlen(buf));
313 
314     SetAPen(rp, cmap_white);
315     Move(rp, cols[cno] - (l / 2), tomb_line - 1);
316     Text(rp, buf, strlen(buf));
317 
318     SetAPen(rp, cmap_white);
319     Move(rp, cols[cno] - (l / 2), tomb_line + 1);
320     Text(rp, buf, strlen(buf));
321 
322     SetAPen(rp, cmap_black);
323     Move(rp, cols[cno] - (l / 2), tomb_line);
324     Text(rp, buf, strlen(buf));
325 }
326 
327 /* search colormap for best match to given color */
328 static int
search_cmap(int r0,int g0,int b0)329 search_cmap(int r0, int g0, int b0)
330 {
331     int best = 0;
332     int bdiff = 0x0fffffff;
333     int x;
334     for (x = 0; x < amii_numcolors; x++) {
335         int r = r0 - ((amiv_init_map[x] >> 8) & 15);
336         int g = g0 - ((amiv_init_map[x] >> 4) & 15);
337         int b = b0 - ((amiv_init_map[x]) & 15);
338         int diff = (r * r) + (g * g) + (b * b);
339         if (diff < bdiff) {
340             bdiff = diff;
341             best = x;
342         }
343     }
344     return best;
345 }
346 
347 /* caution: this is NOT general! */
348 static void
dofade(int start,int stop,int inc)349 dofade(int start, int stop, int inc)
350 {
351     int i, j;
352     for (i = start; (i * inc) <= stop; i += inc) {
353         for (j = 0; j < amii_numcolors; ++j) {
354             int r, g, b;
355 
356             r = (amiv_init_map[j] & 0xf00) >> 8;
357             g = (amiv_init_map[j] & 0xf0) >> 4;
358             b = (amiv_init_map[j] & 0xf);
359             r = (r * i) / 16;
360             g = (g * i) / 16;
361             b = (b * i) / 16;
362             transpalette[j] = ((r << 8) | (g << 4) | b);
363         }
364         LoadRGB4(&HackScreen->ViewPort, transpalette, amii_numcolors);
365         Delay(1);
366     }
367 }
368 
369 #endif /* AMII_GRAPHICS */
370 
371 /*
372 TODO:
373         memory leaks
374         fix ReadImageFiles to return error instead of panic on error
375 */
376