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