NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / amiga / winchar.c
blob4e76e47cc5276de90aeba81e57048128f15d6c14
1 /* aNetHack 0.0.1 winchar.c $ANH-Date: 1432512795 2015/05/25 00:13:15 $ $ANH-Branch: master $:$ANH-Revision: 1.8 $ */
2 /* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */
3 /* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993 */
4 /* Copyright (c) Gregg Wonderly, Naperville Illinois, 1994. */
5 /* aNetHack may be freely redistributed. See license for details. */
7 #include <exec/types.h>
8 #include <libraries/iffparse.h>
9 #include <graphics/scale.h>
10 #ifndef _DCC
11 #include <proto/iffparse.h>
12 #endif
14 #ifdef TESTING
15 #include "hack.h"
16 #else
17 #include "NH:src/tile.c"
18 #endif
20 #include "NH:win/share/tile.h"
22 #include "NH:sys/amiga/windefs.h"
23 #include "NH:sys/amiga/winext.h"
24 #include "NH:sys/amiga/winproto.h"
26 #ifdef OPT_DISPMAP
27 #define DISPMAP /* use display_map() from dispmap.s */
28 #endif
30 /* NH:sys/amiga/winvchar.c */
31 int main(int, char **);
32 struct BitMap *MyAllocBitMap(int, int, int, long);
33 void MyFreeBitMap(struct BitMap *);
34 void FreeImageFiles(char **, struct BitMap **);
35 void amiv_flush_glyph_buffer(struct Window *);
36 void amiv_lprint_glyph(winid, int, int);
37 void amii_lprint_glyph(winid, int, int);
38 void amiv_start_glyphout(winid);
39 void amii_end_glyphout(winid);
40 void SetMazeType(MazeType);
41 int GlyphToIcon(int);
42 void amii_start_glyphout(winid);
43 void amii_end_glyphout(winid);
44 void amii_flush_glyph_buffer(struct Window *);
46 int amii_extraplanes = 0;
47 extern int reclip;
49 struct BitMap *MyAllocBitMap(int xsize, int ysize, int depth, long mflags);
50 void MyFreeBitMap(struct BitMap *bmp);
52 #ifdef DISPMAP
53 extern void display_map(struct Window *);
54 #endif
57 * These values will be available from tile.c source
59 * #define MAXMONTILE 335
60 * #define MAXOBJTILE 722
61 * #define MAXOTHTILE 841
64 #define IMGROWS 12
65 #define IMGCOLUMNS 20
66 #define IMGPAGESIZE (IMGROWS * IMGCOLUMNS)
68 #define ID_BMAP MAKE_ID('B', 'M', 'A', 'P') /* The type of form we use */
69 #define ID_BMHD MAKE_ID('B', 'M', 'H', 'D') /* The ILBM bitmap header */
70 #define ID_CAMG MAKE_ID('C', 'A', 'M', 'G') /* The ILBM camg (ignored) */
71 #define ID_CMAP MAKE_ID('C', 'M', 'A', 'P') /* Standard ILBM color map */
72 #define ID_PLNE MAKE_ID('P', 'L', 'N', 'E') /* The plane data */
73 #define ID_PDAT MAKE_ID('P', 'D', 'A', 'T') /* The PDAT structure below */
75 struct PDAT pictdata;
77 #define NUMTILEIMAGES 3
78 char *tileimages[] = {
79 #define TBLMONTILE 0
80 "aNetHack:tiles/monsters.iff",
81 #define TBLOBJTILE 1
82 "aNetHack:tiles/objects.iff",
83 #define TBLOTHTILE 2
84 "aNetHack:tiles/other.iff", 0,
87 struct BitMap *ifftimg[NUMTILEIMAGES], *tile;
89 #ifdef TESTING
90 short pens[NUMDRIPENS] = { 8, 3, 15, 0, 15, 7, 7, 8, 0 };
91 main(int argc, char **argv)
93 BitMapHeader bmhd;
94 struct IntuiMessage *imsg;
95 long code, class;
96 char buf[100];
97 int i, x, y, tbl, done = 0, num;
98 struct Window *w;
99 struct Screen *scr;
101 bmhd = ReadTileImageFiles();
103 scr = OpenScreenTags(
104 NULL, SA_Depth, pictdata.nplanes + amii_extraplanes, SA_DisplayID,
105 DBLNTSC_MONITOR_ID | HIRESLACE_KEY, SA_Overscan, OSCAN_TEXT, SA_Top,
106 0, SA_Left, 0, SA_Width, STDSCREENWIDTH, SA_Height, STDSCREENHEIGHT,
107 SA_Type, CUSTOMSCREEN, SA_DetailPen, 0, SA_BlockPen, 1, SA_Title,
108 "aNetHack Chars", SA_Pens, pens, TAG_DONE);
109 if (scr == NULL) {
110 printf("no screen\n");
111 #undef exit
112 exit(1);
115 w = OpenWindowTags(
116 0, WA_CustomScreen, scr, WA_Flags,
117 WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET,
118 WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS,
119 WA_Left, 0, WA_Top, scr->WBorTop + 1 + 13, WA_MinWidth, 100,
120 WA_MinHeight, 100, WA_MaxWidth, 700, WA_MaxHeight, 1000, WA_Width,
121 640, WA_Height, 340, WA_SmartRefresh, TRUE, TAG_DONE);
122 if (w) {
123 while (!done) {
124 for (i = 0; i < NUMTILEIMAGES * IMGPAGESIZE; ++i) {
125 int dx, dy;
126 tbl = i / IMGPAGESIZE;
127 x = i % IMGPAGESIZE;
128 y = x / IMGCOLUMNS;
129 x = x % IMGCOLUMNS;
130 dx = i % (IMGCOLUMNS * 2);
131 dy = i / (IMGCOLUMNS * 2);
132 BltBitMapRastPort(ifftimg[tbl], x * pictdata.xsize,
133 y * pictdata.ysize, w->RPort,
134 w->BorderLeft + 1 + dx * pictdata.xsize,
135 w->BorderTop + 1 + dy * pictdata.ysize,
136 pictdata.xsize, pictdata.ysize, 0xc0);
138 WaitPort(w->UserPort);
139 while (imsg = (struct IntuiMessage *) GetMsg(w->UserPort)) {
140 class = imsg->Class;
141 code = imsg->Code;
142 ReplyMsg((struct Message *) imsg);
143 switch (class) {
144 case IDCMP_MOUSEBUTTONS: {
145 x = imsg->MouseX - w->BorderLeft;
146 y = imsg->MouseY - w->BorderTop;
147 num = ((y / pictdata.ysize) * IMGCOLUMNS * 2)
148 + (x / pictdata.xsize);
149 sprintf(buf, "Char #%d", num);
150 SetWindowTitles(w, buf, buf);
151 } break;
152 case IDCMP_CLOSEWINDOW:
153 done = 1;
154 break;
158 CloseWindow(w);
159 CloseScreen(scr);
162 FreeImageFiles(tileimages, ifftimg);
164 return (0);
166 #endif
168 BitMapHeader
169 ReadTileImageFiles()
171 char *errstr = NULL;
172 BitMapHeader ret = ReadImageFiles(tileimages, ifftimg, &errstr);
173 if (errstr) {
174 panic(errstr);
176 return ret;
179 BitMapHeader
180 ReadImageFiles(char **filenames, struct BitMap **iffimg, char **errstrp)
182 BitMapHeader *bmhd = NULL, bmhds;
183 unsigned char *cmap;
184 extern int errno;
185 register int i, j;
186 struct IFFHandle *iff;
187 struct StoredProperty *prop;
189 IFFParseBase = OpenLibrary("iffparse.library", 0L);
190 if (!IFFParseBase) {
191 *errstrp = "No iffparse.library";
192 return bmhds;
196 for( i = 0; filenames[i]; ++i )
197 memset( iffimg[i], 0, sizeof( struct BitMap ) );
199 for (i = 0; filenames[i]; ++i) {
200 iff = AllocIFF();
201 if (!iff) {
202 FreeImageFiles(filenames, iffimg);
203 *errstrp = "can't start IFF processing";
204 return bmhds;
206 iff->iff_Stream = Open(filenames[i], MODE_OLDFILE);
207 if (iff->iff_Stream == 0) {
208 char *buf = malloc(100 + strlen(filenames[i]));
209 FreeImageFiles(filenames, iffimg);
210 sprintf(buf, "Can't open %s: %s", filenames[i], strerror(errno));
211 *errstrp = buf;
212 return bmhds;
214 InitIFFasDOS(iff);
215 OpenIFF(iff, IFFF_READ);
216 PropChunk(iff, ID_BMAP, ID_BMHD);
217 PropChunk(iff, ID_BMAP, ID_CMAP);
218 PropChunk(iff, ID_BMAP, ID_CAMG);
219 PropChunk(iff, ID_BMAP, ID_PDAT);
220 StopChunk(iff, ID_BMAP, ID_PLNE);
221 if ((j = ParseIFF(iff, IFFPARSE_SCAN)) != 0) {
222 char *buf = malloc(100);
223 FreeImageFiles(filenames, iffimg);
224 sprintf(buf, "ParseIFF failed for image %d, failure code: %d", i,
226 *errstrp = buf;
227 return bmhds;
230 if (prop = FindProp(iff, ID_BMAP, ID_BMHD)) {
231 bmhd = (BitMapHeader *) prop->sp_Data;
232 } else {
233 FreeImageFiles(filenames, iffimg);
234 CloseIFF(iff);
235 Close(iff->iff_Stream);
236 FreeIFF(iff);
237 *errstrp = "No BMHD CHUNK in file";
238 return bmhds;
241 if (prop = FindProp(iff, ID_BMAP, ID_CMAP)) {
242 cmap = prop->sp_Data;
243 for (j = 0; j < (1L << bmhd->nPlanes) * 3; j += 3) {
244 #if 0
245 /* Some day we will want to use the larger palette
246 * resolution available under v39 and later. i.e.
247 * 32 instead of 12 bits of color. Ususally this
248 * just means shifting the color left by 16-20 bits
249 * depending on what intensity looks best. Experience
250 * says that the higher values are better intensities.
252 * For now though we won't do this. The color table
253 * structure is incompatible with earlier versions of
254 * intuition. We would have to do some funny things
255 * to make 3*AMII_MAXCOLORS longs work like 3*AMII_MAXCOLORS
256 * UWORD's at run time... A union would help, but...
258 if( IntuitionBase->LibNode.lib_Version >= 39 )
260 /* 8 bits of color, so shift to left end. */
261 amiv_init_map[ j+0 ] = cmap[j+0]<<24;
262 amiv_init_map[ j+1 ] = cmap[j+1]<<24;
263 amiv_init_map[ j+2 ] = cmap[j+2]<<24;
265 else
266 #endif
268 /* We can only use 4 bits of the 8 that are stored in the
269 * cmap, so mask them and then shift them into position
270 * for the UWORD value to store.
272 #ifndef TESTING
273 amii_initmap[j / 3] = amiv_init_map[j / 3] =
274 ((cmap[j + 0] >> 4) << 8) | ((cmap[j + 1] >> 4) << 4)
275 | (cmap[j + 2] >> 4);
276 #endif
279 } else {
280 FreeImageFiles(filenames, iffimg);
281 CloseIFF(iff);
282 Close(iff->iff_Stream);
283 FreeIFF(iff);
284 *errstrp = "No CMAP CHUNK in file";
285 return bmhds;
288 if (prop = FindProp(iff, ID_BMAP, ID_PDAT)) {
289 struct PDAT *pp;
291 pp = (struct PDAT *) prop->sp_Data;
292 pictdata = *pp;
293 } else {
294 FreeImageFiles(filenames, iffimg);
295 CloseIFF(iff);
296 Close(iff->iff_Stream);
297 FreeIFF(iff);
298 *errstrp = "No PDAT CHUNK in file";
299 return bmhds;
302 iffimg[i] = MyAllocBitMap(bmhd->w, bmhd->h,
303 pictdata.nplanes + amii_extraplanes,
304 MEMF_CHIP | MEMF_CLEAR);
305 if (iffimg[i] == NULL) {
306 char *buf = malloc(80);
307 FreeImageFiles(filenames, iffimg);
308 sprintf(buf, "Can't allocate bitmap for image %d\n", i);
309 *errstrp = buf;
310 return bmhds;
312 for (j = 0; j < pictdata.nplanes + amii_extraplanes; ++j) {
313 ReadChunkBytes(iff, iffimg[i]->Planes[j],
314 RASSIZE(bmhd->w, bmhd->h));
316 bmhds = *bmhd;
317 CloseIFF(iff);
318 Close(iff->iff_Stream);
319 FreeIFF(iff);
321 CloseLibrary(IFFParseBase);
323 tile = MyAllocBitMap(pictdata.xsize, pictdata.ysize,
324 pictdata.nplanes + amii_extraplanes,
325 MEMF_CHIP | MEMF_CLEAR);
326 if (tile == NULL) {
327 FreeImageFiles(filenames, iffimg);
328 *errstrp = "Can't allocate tile bitmap for scaling";
330 return (bmhds);
333 struct MyBitMap {
334 struct BitMap bm;
335 long mflags;
336 USHORT xsize, ysize;
339 struct BitMap *
340 MyAllocBitMap(int xsize, int ysize, int depth, long mflags)
342 int j;
343 struct MyBitMap *bm;
345 bm = (struct MyBitMap *) alloc(sizeof(*bm));
346 if (!bm)
347 return (NULL);
349 bm->xsize = xsize;
350 bm->ysize = ysize;
351 InitBitMap(&bm->bm, depth, xsize, ysize);
352 for (j = 0; j < depth; ++j) {
353 if (mflags & MEMF_CHIP)
354 bm->bm.Planes[j] = AllocRaster(xsize, ysize);
355 else
356 bm->bm.Planes[j] = AllocMem(RASSIZE(xsize, ysize), mflags);
358 if (bm->bm.Planes[j] == 0) {
359 MyFreeBitMap(&bm->bm);
360 return (NULL);
362 if (mflags & MEMF_CLEAR)
363 memset(bm->bm.Planes[j], 0, RASSIZE(xsize, ysize));
365 return (&bm->bm);
368 void
369 MyFreeBitMap(struct BitMap *bmp)
371 int j;
372 struct MyBitMap *bm = (struct MyBitMap *) bmp;
374 for (j = 0; j < bm->bm.Depth; ++j) {
375 if (bm->bm.Planes[j]) {
376 if (bm->mflags & MEMF_CHIP)
377 FreeRaster(bm->bm.Planes[j], bm->xsize, bm->ysize);
378 else
379 FreeMem(bm->bm.Planes[j], RASSIZE(bm->xsize, bm->ysize));
382 free(bm);
385 #ifdef TESTING
386 void
387 panic(s, a1, a2, a3, a4)
388 char *s;
390 printf(s, a1, a2, a3, a4);
391 putchar('\n');
393 long *
394 alloc(unsigned int x)
396 long *p = (long *) malloc(x);
397 if (!p) {
398 panic("malloc failed");
399 exit(1);
401 return p;
403 #endif
405 void
406 FreeTileImageFiles()
408 FreeImageFiles(tileimages, ifftimg);
411 void
412 FreeImageFiles(char **filenames, struct BitMap **img)
414 register int i;
416 for (i = 0; filenames[i]; ++i) {
417 if (img[i])
418 MyFreeBitMap(img[i]);
421 /* REALLY ugly hack alert! */
422 if (tile && img == ifftimg)
423 MyFreeBitMap(tile);
426 #ifndef TESTING
428 * Define some stuff for our special glyph drawing routines
430 unsigned short glyph_node_index, glyph_buffer_index;
431 #define NUMBER_GLYPH_NODES 80
432 #define GLYPH_BUFFER_SIZE 512
433 struct amiv_glyph_node {
434 short odstx, odsty;
435 short srcx, srcy, dstx, dsty;
436 struct BitMap *bitmap;
438 struct amiv_glyph_node amiv_g_nodes[NUMBER_GLYPH_NODES];
439 static char amiv_glyph_buffer[GLYPH_BUFFER_SIZE];
441 void
442 flush_glyph_buffer(vw)
443 struct Window *vw;
445 if (WINVERS_AMIV)
446 amiv_flush_glyph_buffer(vw);
447 else
448 amii_flush_glyph_buffer(vw);
452 * Routine to flush whatever is buffered
454 void
455 amiv_flush_glyph_buffer(vw)
456 struct Window *vw;
458 #if !defined(DISPMAP) || defined(OPT_DISPMAP)
459 int xsize, ysize, x, y;
460 struct BitScaleArgs bsa;
461 struct BitScaleArgs bsm;
462 struct RastPort rast;
463 struct Window *w = NULL;
464 struct BitMap *imgbm = 0, *bm = 0;
465 int i, k;
466 int scaling_needed;
467 register struct RastPort *rp = vw->RPort;
468 #endif
470 /* If nothing is buffered, return before we do anything */
471 if (glyph_node_index == 0)
472 return;
474 cursor_off(WIN_MAP);
475 amiv_start_glyphout(WIN_MAP);
477 #ifdef OPT_DISPMAP
478 if (sysflags.fast_map) {
479 #endif
480 #ifdef DISPMAP
481 display_map(vw);
482 #endif
483 #ifdef OPT_DISPMAP
484 } else {
485 #endif
486 #if !defined(DISPMAP) || defined(OPT_DISPMAP)
487 /* XXX fix indent */
488 /* This is a dynamic value based on this relationship. */
489 scaling_needed =
490 (pictdata.xsize != mxsize || pictdata.ysize != mysize);
492 /* If overview window is up, set up to render the correct scale there
494 if (WIN_OVER != WIN_ERR && (w = amii_wins[WIN_OVER]->win) != NULL) {
495 InitRastPort(&rast);
497 /* Calculate the x and y size of each tile for a ROWNO by COLNO
498 * map */
499 xsize = (w->Width - w->BorderLeft - w->BorderRight) / COLNO;
500 ysize = (w->Height - w->BorderTop - w->BorderBottom) / ROWNO;
502 /* Get a chip memory bitmap to blit out of */
503 bm = MyAllocBitMap(pictdata.xsize, pictdata.ysize,
504 pictdata.nplanes + amii_extraplanes,
505 MEMF_CLEAR | MEMF_CHIP);
506 if (bm == NULL) {
507 amii_putstr(
508 WIN_MESSAGE, 0,
509 "Can't allocate bitmap for scaling overview window");
512 rast.BitMap = bm;
514 memset(&bsa, 0, sizeof(bsa));
515 bsa.bsa_SrcX = bsa.bsa_SrcY = 0;
516 bsa.bsa_SrcBitMap = tile;
517 bsa.bsa_SrcWidth = pictdata.xsize;
518 bsa.bsa_SrcHeight = pictdata.ysize;
519 bsa.bsa_XSrcFactor = pictdata.xsize;
520 bsa.bsa_YSrcFactor = pictdata.ysize;
521 bsa.bsa_DestX = 0;
522 bsa.bsa_DestY = 0;
523 bsa.bsa_DestWidth = xsize;
524 bsa.bsa_DestHeight = ysize;
525 bsa.bsa_XDestFactor = xsize;
526 bsa.bsa_YDestFactor = ysize;
527 bsa.bsa_DestBitMap = bm;
530 if (scaling_needed) {
531 /* Fill in scaling data for map rendering */
532 memset(&bsm, 0, sizeof(bsm));
533 bsm.bsa_SrcX = bsm.bsa_SrcY = 0;
534 bsm.bsa_SrcBitMap = tile;
536 bsm.bsa_SrcWidth = pictdata.xsize;
537 bsm.bsa_SrcHeight = pictdata.ysize;
539 bsm.bsa_XSrcFactor = pictdata.xsize;
540 bsm.bsa_YSrcFactor = pictdata.ysize;
542 bsm.bsa_DestWidth = mxsize;
543 bsm.bsa_DestHeight = mysize;
545 bsm.bsa_XDestFactor = mxsize;
546 bsm.bsa_YDestFactor = mysize;
547 bsm.bsa_DestBitMap = rp->BitMap;
548 bsm.bsa_DestY = bsm.bsa_DestX = 0;
550 imgbm = MyAllocBitMap(mxsize, mysize,
551 pictdata.nplanes + amii_extraplanes,
552 MEMF_CLEAR | MEMF_CHIP);
553 if (imgbm == NULL) {
554 amii_putstr(WIN_MESSAGE, 0,
555 "Can't allocate scaling bitmap for map window");
556 } else
557 bsm.bsa_DestBitMap = imgbm;
560 /* Go ahead and start dumping the stuff */
561 for (i = 0; i < glyph_node_index; ++i) {
562 /* Do it */
563 register int offx, offy, j;
564 struct BitMap *nodebm = amiv_g_nodes[i].bitmap;
566 /* Get the unclipped coordinates */
567 x = amiv_g_nodes[i].odstx;
568 y = amiv_g_nodes[i].odsty;
570 /* If image is not in CHIP. copy each plane into tile line by line
573 offx = amiv_g_nodes[i].srcx / 8; /* 8 is bits per byte */
574 offy = amiv_g_nodes[i].srcy * nodebm->BytesPerRow;
575 for (j = 0; j < pictdata.nplanes + amii_extraplanes; ++j) {
576 for (k = 0; k < pictdata.ysize; ++k) {
577 /* For a 16x16 tile, this could just be short assignments,
578 * but
579 * this code is generalized to handle any size tile
580 * image...
582 memcpy(tile->Planes[j] + ((k * pictdata.ysize) / 8),
583 nodebm->Planes[j] + offx + offy
584 + (nodebm->BytesPerRow * k),
585 pictdata.ysize / 8);
589 if (!clipping || (x >= clipx && y >= clipy && x < clipxmax
590 && y < clipymax)) {
591 /* scaling is needed, do it */
592 if (scaling_needed) {
593 BitMapScale(&bsm);
594 BltBitMapRastPort(imgbm, 0, 0, rp, amiv_g_nodes[i].dstx,
595 amiv_g_nodes[i].dsty, mxsize, mysize,
596 0xc0);
597 } else {
598 BltBitMapRastPort(tile, 0, 0, rp, amiv_g_nodes[i].dstx,
599 amiv_g_nodes[i].dsty, pictdata.xsize,
600 pictdata.ysize, 0xc0);
603 /* Draw the overview window unless we are scrolling the map raster
604 * around */
605 if (bm && w && reclip != 2) {
606 BitMapScale(&bsa);
607 BltBitMapRastPort(
608 rast.BitMap, 0, 0, w->RPort,
609 w->BorderLeft + amiv_g_nodes[i].odstx * xsize,
610 w->BorderTop + amiv_g_nodes[i].odsty * ysize, xsize,
611 ysize, 0xc0);
615 if (imgbm)
616 MyFreeBitMap(imgbm);
617 if (bm)
618 MyFreeBitMap(bm);
619 #endif /* DISPMAP */
620 #ifdef OPT_DISPMAP
622 #endif
624 amii_end_glyphout(WIN_MAP);
626 /* Clean up */
627 glyph_node_index = glyph_buffer_index = 0;
631 * Glyph buffering routine. Called instead of WindowPuts().
633 void
634 amiv_lprint_glyph(window, color_index, glyph)
635 winid window;
636 int color_index, glyph;
638 int base;
639 struct amii_WinDesc *cw;
640 struct Window *w;
641 int curx;
642 int cury;
643 int tbl, icon;
644 register int xoff, yoff;
646 /* Get the real icon index */
647 if (glyph != NO_GLYPH)
648 icon = GlyphToIcon(glyph);
650 if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL)
651 panic("bad winid in amiv_lprint_glyph: %d", window);
653 w = cw->win;
655 if (glyph != NO_GLYPH && glyph < 10000) {
656 /* decide on which image has the needed picture */
657 if (icon <= MAXMONTILE) {
658 tbl = TBLMONTILE;
659 base = 0;
660 } else if (icon <= MAXOBJTILE) {
661 tbl = TBLOBJTILE;
662 base = MAXMONTILE + 1;
663 } else if (icon <= MAXOTHTILE) {
664 tbl = TBLOTHTILE;
665 base = MAXOBJTILE + 1;
666 } else
667 panic("Bad icon #%d, glyph #%d, only %d icons known\n", icon,
668 glyph, MAXOTHTILE);
670 /* Get the relative offset in the page */
672 /* How many pixels to account for y distance down */
673 yoff = ((icon - base) / pictdata.across) * pictdata.ysize;
675 /* How many pixels to account for x distance across */
676 xoff = ((icon - base) % pictdata.across) * pictdata.xsize;
679 if (glyph >= 10000) {
680 /* Run a single ASCII character out to the rastport right now */
681 char c = glyph - 10000;
682 int xxx, xxy;
683 struct RastPort *rp = w->RPort;
685 Move(rp, xxx = (((cw->curx - clipx) * rp->TxWidth) + w->BorderLeft),
686 xxy = (w->BorderTop + (((cw->cury - clipy) + 1) * rp->TxHeight)
687 + 1));
688 Text(rp, &c, 1);
689 /* XXX this shouldn't be necessary: */
690 if (cw->cursx == xxx && cw->cursy == xxy) {
691 cw->wflags &= ~FLMAP_CURSUP;
693 cw->curx += rp->TxWidth; /* keep things in sync */
694 return;
697 if (cw->type == NHW_MAP) {
698 curx = cw->curx - clipx;
699 cury = cw->cury - clipy;
701 /* See if we're out of glyph nodes */
702 if (glyph_node_index >= NUMBER_GLYPH_NODES)
703 amiv_flush_glyph_buffer(w);
705 /* Fill in the node. */
706 amiv_g_nodes[glyph_node_index].dsty =
707 min(w->BorderTop + (cury * mysize), w->Height - 1);
709 #ifdef OPT_DISPMAP
710 if (sysflags.fast_map) {
711 #endif /* keni */
712 #ifdef DISPMAP
713 /* display_map() needs byte-aligned destinations, and we don't
714 * want to
715 * overwrite the window border.
717 amiv_g_nodes[glyph_node_index].dstx =
718 (w->BorderLeft + 8 + (curx * mxsize)) & -8;
719 #endif
720 #ifdef OPT_DISPMAP
721 } else {
722 #endif
723 #if !defined(DISPMAP) || defined(OPT_DISPMAP)
724 amiv_g_nodes[glyph_node_index].dstx =
725 min(w->BorderLeft + (curx * mxsize), w->Width - 1);
726 #endif
727 #ifdef OPT_DISPMAP
729 #endif
730 amiv_g_nodes[glyph_node_index].odsty = cw->cury;
731 amiv_g_nodes[glyph_node_index].odstx = cw->curx;
732 amiv_g_nodes[glyph_node_index].srcx = xoff;
733 amiv_g_nodes[glyph_node_index].srcy = yoff;
734 amiv_g_nodes[glyph_node_index].bitmap = ifftimg[tbl];
735 ++glyph_node_index;
736 } else {
737 /* Do it */
738 register int j, k, x, y, apen;
739 struct RastPort *rp = w->RPort;
740 x = rp->cp_x - pictdata.xsize - 3;
741 #ifdef OPT_DISPMAP
742 if (sysflags.fast_map) {
743 #endif
744 #ifdef DISPMAP
745 x &= -8;
746 if (x == 0)
747 x = 8;
748 #endif
749 #ifdef OPT_DISPMAP
751 #endif
753 y = rp->cp_y - pictdata.ysize + 1;
755 if (glyph != NO_GLYPH) {
756 struct BitMap *bm = ifftimg[tbl];
758 /* 8 bits per byte */
759 xoff /= 8;
760 yoff *= bm->BytesPerRow;
761 for (j = 0; j < pictdata.nplanes; ++j) {
762 for (k = 0; k < pictdata.ysize; ++k) {
763 memcpy(tile->Planes[j] + ((k * pictdata.ysize) / 8),
764 bm->Planes[j] + xoff + yoff
765 + (bm->BytesPerRow * k),
766 pictdata.ysize / 8);
770 BltBitMapRastPort(tile, 0, 0, rp, x, y, pictdata.xsize,
771 pictdata.ysize, 0xc0);
773 apen = rp->FgPen;
774 SetAPen(rp, sysflags.amii_dripens[SHINEPEN]);
775 Move(rp, x - 1, y + pictdata.ysize);
776 Draw(rp, x - 1, y - 1);
777 Draw(rp, x + pictdata.xsize, y - 1);
778 SetAPen(rp, sysflags.amii_dripens[SHADOWPEN]);
779 Move(rp, x + pictdata.xsize, y);
780 Draw(rp, x + pictdata.xsize, y + pictdata.ysize);
781 Draw(rp, x, y + pictdata.ysize);
782 SetAPen(rp, apen);
783 } else if (x > w->BorderLeft) {
784 int apen, bpen;
785 apen = rp->FgPen;
786 bpen = rp->BgPen;
787 SetAPen(rp, amii_menuBPen);
788 SetBPen(rp, amii_menuBPen);
789 RectFill(rp, x - 1, y - 1, x + pictdata.xsize,
790 y + pictdata.ysize);
791 SetAPen(rp, apen);
792 SetBPen(rp, bpen);
798 * Define some variables which will be used to save context when toggling
799 * back and forth between low level text and console I/O.
801 static long xsave, ysave, modesave, apensave, bpensave;
802 static int usecolor;
805 * The function is called before any glyphs are driven to the screen. It
806 * removes the cursor, saves internal state of the window, then returns.
809 void
810 amiv_start_glyphout(window)
811 winid window;
813 struct amii_WinDesc *cw;
814 struct Window *w;
816 if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL)
817 panic("bad winid %d in start_glyphout()", window);
819 if (cw->wflags & FLMAP_INGLYPH)
820 return;
822 if (!(w = cw->win))
823 panic("bad winid %d, no window ptr set", window);
826 * Save the context of the window
828 xsave = w->RPort->cp_x;
829 ysave = w->RPort->cp_y;
830 modesave = w->RPort->DrawMode;
831 apensave = w->RPort->FgPen;
832 bpensave = w->RPort->BgPen;
835 * Set the mode, and be done with it
837 usecolor = iflags.use_color;
838 iflags.use_color = FALSE;
839 cw->wflags |= FLMAP_INGLYPH;
843 * General cleanup routine -- flushes and restores cursor
845 void
846 amii_end_glyphout(window)
847 winid window;
849 struct amii_WinDesc *cw;
850 struct Window *w;
852 if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL)
853 panic("bad window id %d in amii_end_glyphout()", window);
855 if ((cw->wflags & FLMAP_INGLYPH) == 0)
856 return;
857 cw->wflags &= ~(FLMAP_INGLYPH);
859 if (!(w = cw->win))
860 panic("bad winid %d, no window ptr set", window);
863 * Clean up whatever is left in the buffer
865 iflags.use_color = usecolor;
868 * Reset internal data structs
870 SetAPen(w->RPort, apensave);
871 SetBPen(w->RPort, bpensave);
872 SetDrMd(w->RPort, modesave);
874 Move(w->RPort, xsave, ysave);
877 static maze_type = COL_MAZE_BRICK;
879 void
880 SetMazeType(MazeType t)
882 maze_type = t;
886 GlyphToIcon(int glyph)
888 if (glyph > 10000)
889 return glyph;
890 return (glyph2tile[glyph]);
892 #endif
894 #ifdef AMII_GRAPHICS
895 #ifdef TESTING
897 * Define some stuff for our special glyph drawing routines
899 static unsigned short glyph_node_index, glyph_buffer_index;
900 #define NUMBER_GLYPH_NODES 80
901 #define GLYPH_BUFFER_SIZE 512
902 #endif /* TESTING */
904 struct amii_glyph_node {
905 short x;
906 short y;
907 short len;
908 unsigned char bg_color;
909 unsigned char fg_color;
910 char *buffer;
912 static struct amii_glyph_node amii_g_nodes[NUMBER_GLYPH_NODES];
913 static char amii_glyph_buffer[GLYPH_BUFFER_SIZE];
915 #ifdef TEXTCOLOR
917 * Map our amiga-specific colormap into the colormap specified in color.h.
918 * See winami.c for the amiga specific colormap.
921 int foreg[AMII_MAXCOLORS] = {
922 0, 7, 4, 2, 6, 5, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0
924 int backg[AMII_MAXCOLORS] = {
925 1, 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 1, 6, 5, 3, 1
927 #if 0
928 #define CLR_BLACK 0
929 #define CLR_RED 1
930 #define CLR_GREEN 2
931 #define CLR_BROWN 3 /* on IBM, low-intensity yellow is brown */
932 #define CLR_BLUE 4
933 #define CLR_MAGENTA 5
934 #define CLR_CYAN 6
935 #define CLR_GRAY 7 /* low-intensity white */
936 #define NO_COLOR 8
937 #define CLR_ORANGE 9
938 #define CLR_BRIGHT_GREEN 10
939 #define CLR_YELLOW 11
940 #define CLR_BRIGHT_BLUE 12
941 #define CLR_BRIGHT_MAGENTA 13
942 #define CLR_BRIGHT_CYAN 14
943 #define CLR_WHITE 15
944 #define CLR_MAX 16
945 #endif
946 #endif
948 #ifndef TESTING
950 * Begin Revamped Text display routines
952 * Up until version 3.1, the only method for displaying text on the playing
953 * field was by using the console.device. This was nice for a number of
954 * reasons, the most signifigant of which was a lot of the nuts and bolts was
955 * done for you via escape sequences interpreted by said device. This did
956 * not come without a price however. And that price was speed. It has now
957 * come to a point where the speed has now been deemed unacceptable.
959 * The following series of routines are designed to drop into the current
960 * anethack display code, using hooks provided for such a measure. It works
961 * on similar principals as the WindowPuts(), buffering I/O internally
962 * until either an explicit flush or internal buffering is exceeded, thereby
963 * forcing the flush. The output (or glyphs) does not go to the
964 * console.device, however. It is driven directly to the rasterport of the
965 * anethack window via the low-level Text() calls, increasing the speed by
966 * a very signifigant factor.
969 * Routine to simply flush whatever is buffered
971 void
972 amii_flush_glyph_buffer(w)
973 struct Window *w;
975 short i, x, y;
976 register struct RastPort *rp = w->RPort;
978 /* If nothing is buffered, return before we do anything */
979 if (glyph_node_index == 0)
980 return;
982 cursor_off(WIN_MAP);
983 amii_start_glyphout(WIN_MAP);
985 /* Set up the drawing mode */
986 SetDrMd(rp, JAM2);
988 /* Go ahead and start dumping the stuff */
989 for (i = 0; i < glyph_node_index; ++i) {
990 /* These coordinate calculations must be synced with the
991 * code in amii_curs() in winfuncs.c. curs_on_u() calls amii_curs()
992 * to draw the cursor on top of the player
994 y = w->BorderTop + (amii_g_nodes[i].y - 2) * rp->TxHeight
995 + rp->TxBaseline + 1;
996 x = amii_g_nodes[i].x * rp->TxWidth + w->BorderLeft;
998 /* Move pens to correct location */
999 Move(rp, (long) x, (long) y);
1001 /* Setup the colors */
1002 SetAPen(rp, (long) amii_g_nodes[i].fg_color);
1003 SetBPen(rp, (long) amii_g_nodes[i].bg_color);
1005 /* Do it */
1006 Text(rp, amii_g_nodes[i].buffer, amii_g_nodes[i].len);
1009 amii_end_glyphout(WIN_MAP);
1010 /* Clean up */
1011 glyph_node_index = glyph_buffer_index = 0;
1013 void
1014 amiga_print_glyph(window, color_index, glyph)
1015 winid window;
1016 int color_index, glyph;
1018 if (WINVERS_AMIV)
1019 amiv_lprint_glyph(window, color_index, glyph);
1020 else
1021 amii_lprint_glyph(window, color_index, glyph);
1025 * Glyph buffering routine. Called instead of WindowPuts().
1027 void
1028 amii_lprint_glyph(window, color_index, glyph)
1029 winid window;
1030 int color_index, glyph;
1032 int fg_color, bg_color;
1033 struct amii_WinDesc *cw;
1034 struct Window *w;
1035 int curx;
1036 int cury;
1038 if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL)
1039 panic("bad winid in amii_lprint_glyph: %d", window);
1041 w = cw->win;
1042 curx = cw->curx;
1043 cury = cw->cury;
1045 #ifdef TEXTCOLOR
1046 fg_color = foreg[color_index];
1047 bg_color = backg[color_index];
1048 #else
1049 fg_color = 1;
1050 bg_color = 0;
1051 #endif /* TEXTCOLOR */
1053 /* See if we have enough character buffer space... */
1054 if (glyph_buffer_index >= GLYPH_BUFFER_SIZE)
1055 amii_flush_glyph_buffer(w);
1058 * See if we can append it to the current active node of glyph buffer. It
1059 * must satisfy the following conditions:
1061 * * background colors are the same, AND
1062 * * foreground colors are the same, AND
1063 * * they are precisely side by side
1065 if ((glyph_buffer_index != 0)
1066 && (fg_color == amii_g_nodes[glyph_node_index - 1].fg_color)
1067 && (bg_color == amii_g_nodes[glyph_node_index - 1].bg_color)
1068 && (amii_g_nodes[glyph_node_index - 1].x
1069 + amii_g_nodes[glyph_node_index - 1].len
1070 == curx) && (amii_g_nodes[glyph_node_index - 1].y == cury)) {
1072 * Add it to the end of the buffer
1074 amii_glyph_buffer[glyph_buffer_index++] = glyph;
1075 amii_g_nodes[glyph_node_index - 1].len++;
1076 } else {
1077 /* See if we're out of glyph nodes */
1078 if (glyph_node_index >= NUMBER_GLYPH_NODES)
1079 amii_flush_glyph_buffer(w);
1080 amii_g_nodes[glyph_node_index].len = 1;
1081 amii_g_nodes[glyph_node_index].x = curx;
1082 amii_g_nodes[glyph_node_index].y = cury;
1083 amii_g_nodes[glyph_node_index].fg_color = fg_color;
1084 amii_g_nodes[glyph_node_index].bg_color = bg_color;
1085 amii_g_nodes[glyph_node_index].buffer =
1086 &amii_glyph_buffer[glyph_buffer_index];
1087 amii_glyph_buffer[glyph_buffer_index] = glyph;
1088 ++glyph_buffer_index;
1089 ++glyph_node_index;
1092 #endif /* !TESTING */
1094 #ifdef TESTING
1096 * Define some variables which will be used to save context when toggling
1097 * back and forth between low level text and console I/O.
1099 static long xsave, ysave, modesave, apensave, bpensave;
1100 static int usecolor;
1101 #endif /* TESTING */
1103 #ifndef TESTING
1105 * The function is called before any glyphs are driven to the screen. It
1106 * removes the cursor, saves internal state of the window, then returns.
1109 void
1110 amii_start_glyphout(window)
1111 winid window;
1113 struct amii_WinDesc *cw;
1114 struct Window *w;
1116 if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL)
1117 panic("bad winid %d in start_glyphout()", window);
1119 if (cw->wflags & FLMAP_INGLYPH)
1120 return;
1122 if (!(w = cw->win))
1123 panic("bad winid %d, no window ptr set", window);
1126 * Save the context of the window
1128 xsave = w->RPort->cp_x;
1129 ysave = w->RPort->cp_y;
1130 modesave = w->RPort->DrawMode;
1131 apensave = w->RPort->FgPen;
1132 bpensave = w->RPort->BgPen;
1135 * Set the mode, and be done with it
1137 usecolor = iflags.use_color;
1138 iflags.use_color = FALSE;
1139 cw->wflags |= FLMAP_INGLYPH;
1141 #endif /* !TESTING */
1143 #if 0
1145 * General cleanup routine -- flushes and restores cursor
1147 void
1148 amii_end_glyphout(window)
1149 winid window;
1151 struct amii_WinDesc *cw;
1152 struct Window *w;
1154 if( ( cw = amii_wins[ window ] ) == (struct amii_WinDesc *)NULL )
1155 panic("bad window id %d in amii_end_glyphout()", window );
1157 if( ( cw->wflags & FLMAP_INGLYPH ) == 0 )
1158 return;
1159 cw->wflags &= ~(FLMAP_INGLYPH);
1161 if( !(w = cw->win ) )
1162 panic( "bad winid %d, no window ptr set", window );
1165 * Clean up whatever is left in the buffer
1167 iflags.use_color = usecolor;
1170 * Reset internal data structs
1172 SetAPen(w->RPort, apensave);
1173 SetBPen(w->RPort, bpensave);
1174 SetDrMd(w->RPort, modesave);
1176 Move(w->RPort, xsave, ysave);
1178 #endif
1179 #endif
1181 #ifndef TESTING
1182 #ifdef OPT_DISPMAP
1183 /* don't use dispmap unless x & y are 8,16,24,32,48 and equal */
1184 void
1185 dispmap_sanity()
1187 if (mxsize != mysize || dispmap_sanity1(mxsize)
1188 || dispmap_sanity1(mysize)) {
1189 sysflags.fast_map = 0;
1193 dispmap_sanity1(x)
1194 int x;
1196 static unsigned char valid[] = { 8, 16, 24, 32, 48, 0 };
1197 return !!strchr(valid, x);
1199 #endif /* OPT_DISPMAP */
1200 #endif /* TESTING */