diff --git a/.gitignore b/.gitignore index f5a18b7e3..68c544da6 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,5 @@ bundle/* util/*.lib util/*.exp submodules/CHKSUMS.tmp +sys/amiga/regex/ +sys/amiga/regex/ diff --git a/dat/symbols b/dat/symbols index af6c04ade..f2bc486fa 100644 --- a/dat/symbols +++ b/dat/symbols @@ -895,4 +895,82 @@ start: Enhanced1 G_trwall_mines: U+251C/113-126-142 finish +start: AmigaFont + Description: Amiga hack.font line-drawing and effect characters + # Dungeon features + S_stone: \x20 + S_vwall: \xc0 + S_hwall: \xc1 + S_tlcorn: \xc2 + S_trcorn: \xc3 + S_blcorn: \xc4 + S_brcorn: \xc5 + S_crwall: \xc6 + S_tuwall: \xd8 + S_tdwall: \xd6 + S_tlwall: \xd7 + S_trwall: \xd5 + S_ndoor: \xd9 + S_vodoor: \x91 + S_hodoor: \x92 + S_vcdoor: \x93 + S_hcdoor: \x94 + S_bars: '#' + S_tree: '#' + S_room: '.' + S_darkroom: \x20 + S_corr: \xe5 + S_litcorr: \xe5 + S_upstair: '<' + S_dnstair: '>' + S_upladder: '<' + S_dnladder: '>' + S_altar: '_' + S_grave: \x5c + S_throne: '#' + S_sink: '{' + S_fountain: '}' + S_pool: '*' + S_ice: '}' + S_lava: '*' + S_vodbridge: '*' + S_hodbridge: '#' + S_vcdbridge: '#' + S_hcdbridge: '.' + S_air: '#' + S_cloud: '}' + # Traps: all default to '^' except web + S_web: '"' + # Effects + S_vbeam: \xf1 + S_hbeam: \xf0 + S_lslant: \xf2 + S_rslant: \xf3 + S_digbeam: '*' + S_flashbeam: '!' + S_boomleft: '{' + S_boomright: '}' + S_ss1: '@' + S_ss2: '&' + S_ss3: '*' + S_ss4: '#' + S_sw_tl: \xf4 + S_sw_tc: \xf5 + S_sw_tr: \xf6 + S_sw_ml: \xf7 + S_sw_mr: \xef + S_sw_bl: \xf8 + S_sw_bc: \xf9 + S_sw_br: \xfa + S_explode1: \xe6 + S_explode2: \xea + S_explode3: \xe7 + S_explode4: \xec + S_explode5: \xd4 + S_explode6: \xed + S_explode7: \xe8 + S_explode8: \xeb + S_explode9: \xe9 +finish + # symbols EOF diff --git a/outdated/include/amiconf.h b/include/amiconf.h similarity index 96% rename from outdated/include/amiconf.h rename to include/amiconf.h index d09801509..b607fd228 100644 --- a/outdated/include/amiconf.h +++ b/include/amiconf.h @@ -48,13 +48,9 @@ typedef long off_t; #define PATHLEN 130 /* data librarian defs */ -#ifndef NOCWD_ASSUMPTIONS -#define DLBFILE "NetHack:nhdat" /* main library */ -#define DLBFILE2 "NetHack:nhsdat" /* sound library */ -#else #define DLBFILE "nhdat" /* main library */ -#define DLBFILE2 "nhsdat" /* sound library */ -#endif +/* nhsdat sound library not used in 3.7 */ +#undef DLBFILE2 #ifndef CROSS_TO_AMIGA #define FILENAME_CMP stricmp /* case insensitive */ diff --git a/include/config1.h b/include/config1.h index 3a8632564..402e0e73c 100644 --- a/include/config1.h +++ b/include/config1.h @@ -95,7 +95,7 @@ #undef UNIX #define DLB #define HACKDIR "NetHack:" -#define NO_MACRO_CPATH + #endif /* diff --git a/include/winami.h b/include/winami.h index b9fbfb65c..1cfd85078 100644 --- a/include/winami.h +++ b/include/winami.h @@ -22,6 +22,7 @@ typedef struct amii_mi { char gselector; /* Group selector */ char canselect; /* Can user select this entry. */ char attr; /* Attribute for the line. */ + int color; /* Color for the line (from menucolors). */ char *str; /* The text of the item. */ } amii_menu_item; diff --git a/include/winprocs.h b/include/winprocs.h index c77288891..688d76138 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -13,8 +13,11 @@ enum wp_ids { wp_tty = 1, wp_X11, wp_Qt, wp_mswin, wp_curses, wp_chainin, wp_chainout, wp_safestartup, wp_shim, wp_hup, wp_guistubs, wp_ttystubs, +#if defined(AMIGA) + wp_amii, wp_amiv, +#endif #ifdef OUTDATED_STUFF - wp_mac, wp_Gem, wp_Gnome, wp_amii, wp_amiv, + wp_mac, wp_Gem, wp_Gnome, #endif wp_trace // XXX do we need this? should chainin/out get an id? TBD }; diff --git a/src/allmain.c b/src/allmain.c index 0b7dd4cab..b53f92fe0 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -13,6 +13,7 @@ staticfn void moveloop_preamble(boolean); staticfn void u_calc_moveamt(int); + staticfn void maybe_do_tutorial(void); #ifdef POSITIONBAR staticfn void do_positionbar(void); @@ -511,11 +512,6 @@ moveloop_core(void) return; } -#ifdef CLIPPING - /* just before rhack */ - cliparound(u.ux, u.uy); -#endif - u.umoved = FALSE; if (gm.multi > 0) { @@ -546,6 +542,11 @@ moveloop_core(void) if (gv.vision_full_recalc) vision_recalc(0); /* vision! */ +#ifdef CLIPPING + /* after rhack() and vision_recalc() so that the map is redrawn + once with correct vision data, not twice (overshoot+correct) */ + cliparound(u.ux, u.uy); +#endif /* when running in non-tport mode, this gets done through domove() */ if ((!svc.context.run || flags.runmode == RUN_TPORT) && (gm.multi && (!svc.context.travel ? !(gm.multi % 7) diff --git a/src/rip.c b/src/rip.c index d482eb0a2..c9c64dfae 100644 --- a/src/rip.c +++ b/src/rip.c @@ -9,7 +9,8 @@ necessarily have to be used by a binary with multiple window-ports */ #if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) \ - || defined(DUMPLOG) || defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS) + || defined(DUMPLOG) || defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS) \ + || defined(AMII_GRAPHICS) #define TEXT_TOMBSTONE #endif #if defined(mac) || defined(__BEOS__) diff --git a/sys/amiga/README.amiga b/sys/amiga/README.amiga new file mode 100644 index 000000000..6aa2a2a95 --- /dev/null +++ b/sys/amiga/README.amiga @@ -0,0 +1,107 @@ + NetHack 3.7 for Amiga + ==================== + +Requirements +------------ + - AmigaOS 3.0 or later (Kickstart 39+) + - 6 MB free RAM minimum (8 MB recommended) + - Hard drive with ~5 MB free space + +Recommended: RTG graphics card (Picasso96/CyberGraphX) for best +tile rendering. Native AGA/OCS/ECS chipsets are supported. + + +Installation +------------ +Extract NH370AMI.ZIP to a directory and assign it: + + assign NetHack: + +The directory should contain: + nethack - game binary + nhdat - data library + symbols - symbol set definitions + sysconf - system configuration + nethack.cnf - game options + hack.font - font descriptor + hack/8 - font bitmap (8pt) + tiles/tiles16.iff - 16-color tiles (OCS/ECS) + tiles/tiles32.iff - 32-color tiles (AGA/RTG) + tomb.iff - tombstone image + record - high score file + +To play: + cd NetHack: + nethack + + +Display Modes +------------- +Two display modes are available, selected in nethack.cnf: + + Text mode (AMII): + OPTIONS=symset:AmigaFont + + Tile mode (AMIV): + OPTIONS=windowtype:amiv + +Tile mode auto-selects tiles32.iff (32 colors, 5 bitplanes) when the +screen supports 32+ colors, otherwise tiles16.iff (16 colors, 4 planes). + + +Configuration +------------- +Edit nethack.cnf for game options. Key settings: + + OPTIONS=windowtype:amiv - tile graphics (default) + OPTIONS=symset:AmigaFont - text mode with line-drawing chars + OPTIONS=menucolors - colored inventory items + OPTIONS=time,lit_corridor - show turn count, lit corridors + OPTIONS=boulder:0 - display boulders as '0' + +Menu color examples (add after OPTIONS=menucolors): + MENUCOLOR=" blessed "=green + MENUCOLOR=" cursed "=red + MENUCOLOR=" uncursed "=cyan + + +Building from Source +-------------------- +Cross-compilation from Linux using bebbo's m68k-amigaos-gcc toolchain +(https://franke.ms/git/bebbo/amiga-gcc): + + # Install toolchain to /opt/amiga + # Clone NetHack 3.7 source + cd NetHack + sys/unix/setup.sh sys/unix/hints/linux.370 + make fetch-lua + make CROSS_TO_AMIGA=1 fetch-regex + make CROSS_TO_AMIGA=1 all + make CROSS_TO_AMIGA=1 package + +The distribution ZIP is created at targets/amiga/NH370AMI.ZIP. + +Toolchain requirements: + - m68k-amigaos-gcc (bebbo's amigaos-cross-toolchain in /opt/amiga) + - -noixemul (libnix) for linking + - -m68000 for maximum compatibility (or -m68020/040/060) + + +Known Issues +------------ + - Native Amiga compilation (SAS/C, DICE) is not supported; + cross-compilation with GCC is required + + +Credits +------- +Olaf Seibert first ported NetHack 2.3 and 3.0 to the Amiga. +Richard Addison, Andrew Church, Jochen Erwied, Mark Gooderum, +Ken Lorber, Greg Olson, Mike Passaretti, and Gregg Wonderly +polished and extended the 3.0 and 3.1 ports. Andrew Church, +Ken Lorber, and Gregg Wonderly are responsible for the 3.2 port. +Janne Salmijärvi resurrected the Amiga port for 3.3 and +Teemu Suikki joined before 3.4.0. + +Updated for NetHack 3.7, cross compile fixes and 32 color tile support by Ingo +Paschke in 2026. diff --git a/outdated/sys/amiga/amidos.c b/sys/amiga/amidos.c similarity index 91% rename from outdated/sys/amiga/amidos.c rename to sys/amiga/amidos.c index 6ec41b5de..3d465ddd2 100644 --- a/outdated/sys/amiga/amidos.c +++ b/sys/amiga/amidos.c @@ -9,6 +9,7 @@ #include "hack.h" #include "winami.h" +#include "windefs.h" /* Defined in config.h, let's undefine it here (static function below) */ #undef strcmpi @@ -18,11 +19,17 @@ #include #undef COUNT + #if defined(__SASC_60) || defined(__GNUC__) #include #include #endif +/* POSIX stubs needed by libnix (-noixemul) */ +#ifdef __noixemul__ +int getpid(void) { return (int)FindTask(NULL); } +#endif + #ifdef AZTEC_50 #include #undef strcmpi @@ -34,11 +41,12 @@ #include "NH:sys/amiga/winami.p" #include "NH:sys/amiga/amidos.p" #else -#include "winami.p" +#include "amiwind.p" #include "winami.p" #include "amidos.p" #endif + extern char Initialized; extern struct window_procs amii_procs; struct ami_sysflags sysflags = {0}; @@ -54,13 +62,14 @@ char PATH[PATHLEN] = "NetHack:"; static boolean record_exists(void); void -flushout() +flushout(void) { (void) fflush(stdout); } #ifndef getuid -getuid() +int +getuid(void) { return 1; } @@ -68,26 +77,19 @@ getuid() #ifndef getlogin char * -getlogin() +getlogin(void) { return ((char *) NULL); } #endif -#ifndef AZTEC_50 -int -abs(x) -int x; -{ - return x < 0 ? -x : x; -} -#endif +/* abs() provided by libnix/stdlib */ #ifdef SHELL int -dosh() +dosh(void) { - int i; + int i = 0; char buf[BUFSZ]; extern struct ExecBase *SysBase; @@ -121,8 +123,7 @@ dosh() */ /* TODO: update this for FFS */ long -freediskspace(path) -char *path; +freediskspace(char *path) { #ifdef UNTESTED /* these changes from Patric Mueller for AROS to @@ -131,9 +132,9 @@ char *path; */ unsigned long long freeBytes = 0; #else - register long freeBytes = 0; + long freeBytes = 0; #endif - register struct InfoData *infoData; /* Remember... longword aligned */ + struct InfoData *infoData; /* Remember... longword aligned */ char fileName[32]; /* @@ -145,7 +146,7 @@ char *path; * so must be on the current device, so "" is enough... */ { - register char *colon; + char *colon; strncpy(fileName, path, sizeof(fileName) - 1); fileName[31] = 0; @@ -191,12 +192,11 @@ char *path; } long -filesize(file) -char *file; +filesize(char *file) { - register BPTR fileLock; - register struct FileInfoBlock *fileInfoBlock; - register long size = 0; + BPTR fileLock; + struct FileInfoBlock *fileInfoBlock; + long size = 0; fileInfoBlock = (struct FileInfoBlock *) alloc(sizeof(struct FileInfoBlock)); @@ -212,8 +212,8 @@ char *file; #if 0 void -eraseall(path, files) -const char *path, *files; +void +eraseall(const char *path, const char *files) { BPTR dirLock, dirLock2; struct FileInfoBlock *fibp; @@ -248,12 +248,11 @@ const char *path, *files; #if 0 /* Unused */ #define COPYSIZE 4096 -char *CopyFile(from, to) -const char *from, *to; +char *CopyFile(const char *from, const char *to) { - register BPTR fromFile, toFile; - register char *buffer; - register long size; + BPTR fromFile, toFile; + char *buffer; + long size; char *error = NULL; buffer = (char *) alloc(COPYSIZE); @@ -282,7 +281,8 @@ const char *from, *to; #ifdef MFLOPPY /* this should be replaced */ -saveDiskPrompt(start) +int +saveDiskPrompt(int start) { char buf[BUFSIZ], *bp; BPTR fileLock; @@ -338,7 +338,7 @@ saveDiskPrompt(start) /* Return 1 if the record file was found */ static boolean -record_exists() +record_exists(void) { FILE *file; @@ -355,7 +355,7 @@ record_exists() * For Amiga: do nothing, but called from restore.c */ void -gameDiskPrompt() +gameDiskPrompt(void) { } #endif @@ -365,8 +365,7 @@ gameDiskPrompt() * be room for the /. */ void -append_slash(name) -char *name; +append_slash(char *name) { char *ptr; @@ -381,8 +380,7 @@ char *name; } void -getreturn(str) -const char *str; +getreturn(const char *str) { int ch; @@ -396,12 +394,11 @@ const char *str; #define PATHSEP ';' FILE * -fopenp(name, mode) -register const char *name, *mode; +fopenp(const char *name, const char *mode) { - register char *bp, *pp, lastch; - register FILE *fp; - register BPTR theLock; + char *bp, *pp, lastch = 0; + FILE *fp; + BPTR theLock; char buf[BUFSIZ]; /* Try the default directory first. Then look along PATH. @@ -452,7 +449,8 @@ register const char *name, *mode; static BPTR OrgDirLock = NO_LOCK; -chdir(dir) char *dir; +int +chdir(char *dir) { extern char orgdir[]; @@ -489,7 +487,7 @@ chdir(dir) char *dir; */ #undef exit void -nethack_exit(code) +nethack_exit(int code) { #ifdef CHDIR extern char orgdir[]; @@ -506,10 +504,10 @@ nethack_exit(code) exit(code); } -void regularize(s) /* normalize file name - we don't like :'s or /'s */ -register char *s; +void +regularize(char *s) /* normalize file name - we don't like :'s or /'s */ { - register char *lp; + char *lp; while ((lp = strchr(s, ':')) || (lp = strchr(s, '/'))) *lp = '_'; diff --git a/outdated/sys/amiga/amidos.p b/sys/amiga/amidos.p similarity index 100% rename from outdated/sys/amiga/amidos.p rename to sys/amiga/amidos.p diff --git a/outdated/sys/amiga/amifont.uu b/sys/amiga/amifont.uu similarity index 100% rename from outdated/sys/amiga/amifont.uu rename to sys/amiga/amifont.uu diff --git a/outdated/sys/amiga/amifont8.uu b/sys/amiga/amifont8.uu similarity index 100% rename from outdated/sys/amiga/amifont8.uu rename to sys/amiga/amifont8.uu diff --git a/outdated/sys/amiga/amigst.c b/sys/amiga/amigst.c similarity index 100% rename from outdated/sys/amiga/amigst.c rename to sys/amiga/amigst.c diff --git a/outdated/sys/amiga/amii.hlp b/sys/amiga/amii.hlp similarity index 100% rename from outdated/sys/amiga/amii.hlp rename to sys/amiga/amii.hlp diff --git a/outdated/sys/amiga/amimenu.c b/sys/amiga/amimenu.c similarity index 100% rename from outdated/sys/amiga/amimenu.c rename to sys/amiga/amimenu.c diff --git a/outdated/sys/amiga/amirip.c b/sys/amiga/amirip.c similarity index 93% rename from outdated/sys/amiga/amirip.c rename to sys/amiga/amirip.c index b14689f80..5f4aa52af 100644 --- a/outdated/sys/amiga/amirip.c +++ b/sys/amiga/amirip.c @@ -43,15 +43,15 @@ static struct RastPort *rp; #include #endif -static char *load_list[] = { "tomb.iff", 0 }; static BitMapHeader tomb_bmhd; -static struct BitMap *tbmp[1] = { 0 }; +static struct BitMap *tombimg = NULL; -static int cols[2] = { 154, 319 }; /* X location of center of columns */ +static const int cols_base[2] = { 154, 319 }; /* X location of center of columns */ +static int cols[2]; /* cols_base[] + xoff, computed per call */ static int cno = 0; /* current column */ #define TEXT_TOP (65 + yoff) -static xoff, yoff; /* image centering */ +static int xoff, yoff; /* image centering */ /* terrible kludge */ /* this is why prototypes should have ONLY types in them! */ @@ -100,19 +100,16 @@ int wh; /* was local in outrip, but needed for SCALE macro */ int cmap_white, cmap_black; void -amii_outrip(tmpwin, how, when) -winid tmpwin; -int how; -time_t when; +amii_outrip(winid tmpwin, int how, time_t when) { int just_return = 0; int done, rtxth; + struct IntuiMessage *imsg; int i; - register char *dpx; + char *dpx; char buf[200]; int line, tw, ww; - char *errstr = NULL; long year; if (!WINVERS_AMIV || HackScreen->RastPort.BitMap->Depth < 4) @@ -141,9 +138,7 @@ time_t when; SetFont(rp, HackFont); #endif - tomb_bmhd = ReadImageFiles(load_list, tbmp, &errstr); - if (errstr) - goto cleanup; + tomb_bmhd = ReadImageFile("tomb.iff", &tombimg); if (tomb_bmhd.w > ww || tomb_bmhd.h > wh) goto cleanup; @@ -151,12 +146,12 @@ time_t when; xoff = GENOFF(ww, tomb_bmhd.w); yoff = GENOFF(wh, tomb_bmhd.h); for (i = 0; i < SIZE(cols); i++) - cols[i] += xoff; + cols[i] = cols_base[i] + xoff; cmap_white = search_cmap(0, 0, 0); cmap_black = search_cmap(15, 15, 15); - BltBitMap(*tbmp, 0, 0, rp->BitMap, xoff, yoff, tomb_bmhd.w, tomb_bmhd.h, + BltBitMap(tombimg, 0, 0, rp->BitMap, xoff, yoff, tomb_bmhd.w, tomb_bmhd.h, 0xc0, 0xff, NULL); /* Put together death description */ @@ -199,7 +194,7 @@ time_t when; /* Put death type on stone */ for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) { - register int i, i0; + int i, i0; char tmpchar; if ((i0 = strlen(dpx)) > STONE_LINE_LEN) { @@ -280,8 +275,7 @@ cleanup: } LoadRGB4(&HackScreen->ViewPort, sysflags.amii_curmap, amii_numcolors); - if (tbmp[0]) - FreeImageFiles(load_list, tbmp); + FreeImageFile(&tombimg); if (just_return) return; /* fall back to the straight-ASCII version */ @@ -289,8 +283,7 @@ cleanup: } static void -tomb_text(p) -char *p; +tomb_text(char *p) { char buf[STONE_LINE_LEN * 2]; int l; diff --git a/outdated/sys/amiga/amistack.c b/sys/amiga/amistack.c similarity index 55% rename from outdated/sys/amiga/amistack.c rename to sys/amiga/amistack.c index 33769697f..e0ea10a7b 100644 --- a/outdated/sys/amiga/amistack.c +++ b/sys/amiga/amistack.c @@ -1,5 +1,5 @@ /* NetHack 3.6 amistack.c $NHDT-Date: 1432512795 2015/05/25 00:13:15 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */ -/* Copyright (c) Janne Salmijärvi, Tampere, Finland, 2000 */ +/* Copyright (c) Janne Salmij�rvi, Tampere, Finland, 2000 */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -12,10 +12,16 @@ #ifdef __SASC_60 #include +#endif /* - * At the moment 90*1024 would suffice, but just to be on the safe side ... + * Increase stack size to allow deep recursions. + * NetHack 3.7 with Lua needs significantly more stack than 3.6. */ -long __stack = 128 * 1024; +#ifdef __SASC_60 +long __stack = 256 * 1024; +#else +/* For GCC with -noixemul (libnix), __stack is also recognized */ +unsigned long __stack = 256 * 1024; #endif diff --git a/outdated/sys/amiga/amitty.c b/sys/amiga/amitty.c similarity index 97% rename from outdated/sys/amiga/amitty.c rename to sys/amiga/amitty.c index e3ff882ef..22036c8f5 100644 --- a/outdated/sys/amiga/amitty.c +++ b/sys/amiga/amitty.c @@ -23,12 +23,12 @@ void tty_change_color(void); char *tty_get_color_string(void); -#ifdef TTY_GRAPHICS - int amibbs = 0; /* BBS mode */ char bbs_id[80] = ""; /* BBS uid equivalent */ long afh_in, afh_out; /* BBS mode Amiga filehandles */ +#ifdef TTY_GRAPHICS + void settty(const char *s) { @@ -58,9 +58,10 @@ setftty() } char kill_char = 'X' - '@'; char erase_char = '\b'; -tgetch() +int +tgetch(void) { - char x; + unsigned char x; Read(afh_in, &x, 1); return (x == '\r') ? '\n' : x; } diff --git a/outdated/sys/amiga/amiwind.c b/sys/amiga/amiwind.c similarity index 90% rename from outdated/sys/amiga/amiwind.c rename to sys/amiga/amiwind.c index 6a64667eb..e06630675 100644 --- a/outdated/sys/amiga/amiwind.c +++ b/sys/amiga/amiwind.c @@ -23,18 +23,20 @@ static struct Message *GetFMsg(struct MsgPort *); #endif static int BufferGetchar(void); -static void ProcessMessage(register struct IntuiMessage *message); +static void ProcessMessage(struct IntuiMessage *message); #define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch)) -#ifndef CROSS_TO_AMIGA -struct Library *ConsoleDevice; -#else -struct Device * -# ifdef __CONSTLIBBASEDECL__ - __CONSTLIBBASEDECL__ -# endif /* __CONSTLIBBASEDECL__ */ - ConsoleDevice; -#endif + +struct Device *ConsoleDevice = NULL; + +/* Library bases - opened by amii_init_nhwindows, closed by amii_cleanup. + DOSBase is provided by newlib's startup code. + The rest must be defined here. */ +struct IntuitionBase *IntuitionBase = NULL; +struct GfxBase *GfxBase = NULL; +struct Library *GadToolsBase = NULL; +struct Library *LayersBase = NULL; +struct Library *AslBase = NULL; #ifndef CROSS_TO_AMIGA #include "NH:sys/amiga/amimenu.c" @@ -44,7 +46,6 @@ struct Device * /* Now our own variables */ -struct IntuitionBase *IntuitionBase; struct Screen *HackScreen; struct Window *pr_WindowPtr; struct MsgPort *HackPort; @@ -55,7 +56,6 @@ char Initialized = 0; WEVENT lastevent; #ifdef HACKFONT -struct GfxBase *GfxBase; struct Library *DiskfontBase; #endif @@ -100,11 +100,10 @@ static enum { NoAction, CloseOver } delayed_key_action = NoAction; */ struct Window * -OpenShWindow(nw) -struct NewWindow *nw; +OpenShWindow(struct NewWindow *nw) { - register struct Window *win; - register ULONG idcmpflags; + struct Window *win; + ULONG idcmpflags; if (!HackPort) /* Sanity check */ return (struct Window *) 0; @@ -126,12 +125,10 @@ struct NewWindow *nw; * Close a window that shared the HackPort IDCMP port. */ -void CloseShWindow(struct Window *); void -CloseShWindow(win) -struct Window *win; +CloseShWindow(struct Window *win) { - register struct IntuiMessage *msg; + struct IntuiMessage *msg; if (!HackPort) panic("HackPort NULL in CloseShWindow"); @@ -152,9 +149,9 @@ struct Window *win; } static int -BufferGetchar() +BufferGetchar(void) { - register int c; + int c; if (KbdBuffered > 0) { c = KbdBuffer[0]; @@ -180,8 +177,7 @@ BufferGetchar() */ int -ConvertKey(message) -register struct IntuiMessage *message; +ConvertKey(struct IntuiMessage *message) { static struct InputEvent theEvent; static char numpad[] = "bjnh.lyku"; @@ -190,8 +186,8 @@ register struct IntuiMessage *message; unsigned char buffer[10]; struct Window *w = message->IDCMPWindow; - register int length; - register ULONG qualifier; + int length; + ULONG qualifier; char numeric_pad, shift, control, alt; if (amii_wins[WIN_MAP]) @@ -355,10 +351,7 @@ register struct IntuiMessage *message; return (-1); } } - printf("Unrecognized key: %d ", (int) buffer[0]); - for (i = 1; i < length; ++i) - printf("%d ", (int) buffer[i]); - printf("\n"); + /* unrecognized key — silently ignore */ } return (-1); } @@ -373,8 +366,7 @@ register struct IntuiMessage *message; */ static void -ProcessMessage(message) -register struct IntuiMessage *message; +ProcessMessage(struct IntuiMessage *message) { int c; int cnt; @@ -385,15 +377,7 @@ register struct IntuiMessage *message; switch (message->Class) { case ACTIVEWINDOW: - if (alwaysinvent && WIN_INVEN != WIN_ERR - && w == amii_wins[WIN_INVEN]->win) { - cnt = DoMenuScroll(WIN_INVEN, 0, PICK_NONE, &mip); - } else if (scrollmsg && WIN_MESSAGE != WIN_ERR - && w == amii_wins[WIN_MESSAGE]->win) { - cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip); - } else { - skip_mouse = 1; - } + skip_mouse = 1; break; case MOUSEBUTTONS: { @@ -429,12 +413,8 @@ register struct IntuiMessage *message; } } break; - case REFRESHWINDOW: { - if (scrollmsg && amii_wins[WIN_MESSAGE] - && w == amii_wins[WIN_MESSAGE]->win) { - cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip); - } - } break; + case REFRESHWINDOW: + break; case CLOSEWINDOW: if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) { @@ -458,11 +438,6 @@ register struct IntuiMessage *message; break; case GADGETDOWN: - if (WIN_MESSAGE != WIN_ERR && w == amii_wins[WIN_MESSAGE]->win) { - cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip); - } else if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) { - cnt = DoMenuScroll(WIN_INVEN, 0, PICK_NONE, &mip); - } break; case NEWSIZE: @@ -481,7 +456,17 @@ register struct IntuiMessage *message; ReDisplayData(WIN_INVEN); } else if (WINVERS_AMIV && (WIN_OVER != WIN_ERR && w == amii_wins[WIN_OVER]->win)) { - BufferQueueChar('R' - 64); + { + int i, have_redraw = 0; + for (i = 0; i < KbdBuffered; i++) { + if (KbdBuffer[i] == 'R' - 64) { + have_redraw = 1; + break; + } + } + if (!have_redraw) + BufferQueueChar('R' - 64); + } } else if (WIN_MAP != WIN_ERR && w == amii_wins[WIN_MAP]->win) { #ifdef CLIPPING CO = (w->Width - w->BorderLeft - w->BorderRight) / mxsize; @@ -494,7 +479,17 @@ register struct IntuiMessage *message; clipping = FALSE; clipx = clipy = 0; } - BufferQueueChar('R' - 64); + { + int i, have_redraw = 0; + for (i = 0; i < KbdBuffered; i++) { + if (KbdBuffer[i] == 'R' - 64) { + have_redraw = 1; + break; + } + } + if (!have_redraw) + BufferQueueChar('R' - 64); + } #endif } break; @@ -506,8 +501,9 @@ register struct IntuiMessage *message; amii_destroy_nhwindow(WIN_OVER); WIN_OVER = WIN_ERR; delayed_key_action = NoAction; + break; case NoAction: - ; /* null */ + break; } } @@ -522,13 +518,13 @@ register struct IntuiMessage *message; #if defined(TTY_GRAPHICS) && !defined(AMII_GRAPHICS) int -kbhit() +kbhit(void) { return 0; } #else int -kbhit() +kbhit(void) { int c; #ifdef TTY_GRAPHICS @@ -547,9 +543,9 @@ kbhit() #ifdef AMII_GRAPHICS int -amikbhit() +amikbhit(void) { - register struct IntuiMessage *message; + struct IntuiMessage *message; while (KbdBuffered < KBDBUFFER / 2) { #ifdef AMIFLUSH message = (struct IntuiMessage *) GetFMsg(HackPort); @@ -572,7 +568,7 @@ amikbhit() */ int -WindowGetchar() +WindowGetchar(void) { while ((lastevent.type = WEUNK), amikbhit() <= 0) { WaitPort(HackPort); @@ -581,7 +577,7 @@ WindowGetchar() } WETYPE -WindowGetevent() +WindowGetevent(void) { lastevent.type = WEUNK; while (amikbhit() == 0) { @@ -601,9 +597,9 @@ WindowGetevent() */ void -amii_cleanup() +amii_cleanup(void) { - register struct IntuiMessage *msg; + struct IntuiMessage *msg; /* Close things up */ if (HackPort) { @@ -713,8 +709,7 @@ amii_cleanup() #ifndef SHAREDLIB void -Abort(rc) -long rc; +Abort(long rc) { int fault = 1; #ifdef CHDIR @@ -765,7 +760,7 @@ long rc; } void -CleanUp() +CleanUp(void) { amii_cleanup(); } @@ -776,8 +771,7 @@ CleanUp() #ifdef AMIFLUSH /* This routine adapted from AmigaMail IV-37 by Michael Sinz */ static struct Message * -GetFMsg(port) -struct MsgPort *port; +GetFMsg(struct MsgPort *port) { struct IntuiMessage *msg, *succ, *succ1; @@ -803,8 +797,7 @@ struct MsgPort *port; #endif struct NewWindow * -DupNewWindow(win) -struct NewWindow *win; +DupNewWindow(struct NewWindow *win) { struct NewWindow *nwin; struct Gadget *ngd, *gd, *pgd = NULL; @@ -845,11 +838,10 @@ struct NewWindow *win; } void -FreeNewWindow(win) -struct NewWindow *win; +FreeNewWindow(struct NewWindow *win) { - register struct Gadget *gd, *pgd; - register struct StringInfo *sip; + struct Gadget *gd, *pgd; + struct StringInfo *sip; for (gd = win->FirstGadget; gd; gd = pgd) { pgd = gd->NextGadget; @@ -868,7 +860,7 @@ struct NewWindow *win; } void -bell() +bell(void) { if (flags.silent) return; @@ -876,15 +868,14 @@ bell() } void -amii_delay_output() +amii_delay_output(void) { /* delay 50 ms */ Delay(2L); } void -amii_number_pad(state) -int state; +amii_number_pad(int state) { } #endif /* AMII_GRAPHICS */ diff --git a/outdated/sys/amiga/amiwind.p b/sys/amiga/amiwind.p similarity index 100% rename from outdated/sys/amiga/amiwind.p rename to sys/amiga/amiwind.p diff --git a/sys/amiga/bmp2iff_host.c b/sys/amiga/bmp2iff_host.c new file mode 100644 index 000000000..154335297 --- /dev/null +++ b/sys/amiga/bmp2iff_host.c @@ -0,0 +1,480 @@ +/* + * bmp2iff_host.c - Convert a BMP to Amiga BMAP IFF. + * Copyright (c) 2026 by Ingo Paschke. + * NetHack may be freely redistributed. See license for details. + * + * IFF BMAP format matches sys/amiga/xpm2iff.c by Gregg Wonderly. + * + * Usage: bmp2iff_host -planes N input.bmp output.iff + * + * This is a HOST tool -- runs on the build machine. + */ + +#include +#include +#include +#include + +#define TILE_X 16 +#define TILE_Y 16 + +#pragma pack(push,1) +typedef struct { + uint16_t bfType; + uint32_t bfSize; + uint16_t bfReserved1, bfReserved2; + uint32_t bfOffBits; +} BMPFILEHEADER; + +typedef struct { + uint32_t biSize; + int32_t biWidth, biHeight; + uint16_t biPlanes, biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + int32_t biXPelsPerMeter, biYPelsPerMeter; + uint32_t biClrUsed, biClrImportant; +} BMPINFOHEADER; +#pragma pack(pop) + +typedef struct { + uint8_t r, g, b; +} RGB; + +/* --------------------------------------------------------- */ +/* Fixed 16-color AMIV UI palette */ +/* Must match amiv_init_map[] in winami.c */ +/* --------------------------------------------------------- */ + +static const RGB amiv_pal[16] = { + {0x00,0x00,0x00}, /* 0 black */ + {0xFF,0xFF,0xFF}, /* 1 white */ + {0x00,0xBB,0xFF}, /* 2 cyan */ + {0xFF,0x66,0x00}, /* 3 orange */ + {0x00,0x00,0xFF}, /* 4 blue */ + {0x00,0x99,0x00}, /* 5 green */ + {0x66,0x99,0xBB}, /* 6 grey */ + {0xFF,0x00,0x00}, /* 7 red */ + {0x66,0xFF,0x00}, /* 8 ltgreen */ + {0xFF,0xFF,0x00}, /* 9 yellow */ + {0xFF,0x00,0xFF}, /* 10 magenta */ + {0x99,0x44,0x00}, /* 11 brown */ + {0x44,0x66,0x66}, /* 12 greyblue */ + {0xCC,0x44,0x00}, /* 13 ltbrown */ + {0xDD,0xDD,0xBB}, /* 14 ltgrey */ + {0xFF,0xBB,0x99}, /* 15 peach */ +}; + +/* --------------------------------------------------------- */ +/* Colour helpers */ +/* --------------------------------------------------------- */ + +static int +coldist(const RGB *a, const RGB *b) +{ + int dr = a->r - b->r; + int dg = a->g - b->g; + int db = a->b - b->b; + return dr*dr + dg*dg + db*db; +} + +static int +nearest(const RGB *c, const RGB *pal, int n) +{ + int best = 0, bestd = 0x7fffffff, i; + for (i = 0; i < n; i++) { + int d = coldist(c, &pal[i]); + if (d < bestd) { bestd = d; best = i; } + } + return best; +} + +/* --------------------------------------------------------- */ +/* IFF output */ +/* --------------------------------------------------------- */ + +static FILE *iff_fp; + +static void +wr32(uint32_t v) +{ + uint8_t b[4] = { v>>24, v>>16, v>>8, v }; + fwrite(b, 1, 4, iff_fp); +} + +static void +wr_chunk(const char *id, const void *d, uint32_t len) +{ + fwrite(id, 1, 4, iff_fp); + wr32(len); + fwrite(d, 1, len, iff_fp); + if (len & 1) fputc(0, iff_fp); +} + +static void +iff_write(int nplanes, int ncolors, uint8_t *cmap, + int w, int h, uint8_t **planes, + int ntiles, int across, int down) +{ + long spos; + uint32_t plsz = (uint32_t)(w / 8) * h; + int i; + + fwrite("FORM", 1, 4, iff_fp); + spos = ftell(iff_fp); + wr32(0); + fwrite("BMAP", 1, 4, iff_fp); + + /* BMHD */ + { + uint8_t bm[20]; + memset(bm, 0, 20); + bm[0] = w >> 8; bm[1] = w; + bm[2] = h >> 8; bm[3] = h; + bm[8] = (uint8_t)nplanes; + bm[14] = 100; bm[15] = 100; + wr_chunk("BMHD", bm, 20); + } + + /* CAMG */ + { + uint8_t c[4] = {0,0,0x80,0x04}; + wr_chunk("CAMG", c, 4); + } + + /* CMAP */ + wr_chunk("CMAP", cmap, (uint32_t)ncolors * 3); + + /* PDAT */ + { + uint8_t pd[28], *p = pd; + uint32_t v[7]; + v[0] = nplanes; + v[1] = plsz; + v[2] = across; + v[3] = down; + v[4] = ntiles; + v[5] = TILE_X; + v[6] = TILE_Y; + for (i = 0; i < 7; i++) { + p[0] = (v[i]>>24); p[1] = (v[i]>>16); + p[2] = (v[i]>> 8); p[3] = v[i]; + p += 4; + } + wr_chunk("PDAT", pd, 28); + } + + /* PLNE */ + fwrite("PLNE", 1, 4, iff_fp); + wr32(plsz * nplanes); + for (i = 0; i < nplanes; i++) + fwrite(planes[i], 1, plsz, iff_fp); + + /* fix FORM size */ + { + long end = ftell(iff_fp); + uint32_t sz = (uint32_t)(end - spos - 4); + fseek(iff_fp, spos, SEEK_SET); + wr32(sz); + fseek(iff_fp, 0, SEEK_END); + } +} + +/* --------------------------------------------------------- */ +/* Pixel-to-bitplane conversion */ +/* --------------------------------------------------------- */ + +static void +to_planes(uint8_t *pix, int w, int h, + int np, uint8_t **pl) +{ + int rb = w / 8; + int x, y, p; + + for (p = 0; p < np; p++) + memset(pl[p], 0, rb * h); + + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) { + uint8_t v = pix[y * w + x]; + int off = y * rb + x / 8; + int bit = 7 - (x & 7); + for (p = 0; p < np; p++) + if (v & (1 << p)) + pl[p][off] |= (1 << bit); + } +} + +/* --------------------------------------------------------- */ +/* Palette building */ +/* --------------------------------------------------------- */ + +/* + * Build an output palette of 'maxcol' entries: + * - slots 0-15: fixed AMIV UI colors + * - slots 16+: tile colors from the BMP + * + * Returns remap[0..nsrc-1] mapping BMP palette index + * to output palette index. + */ +static void +build_palette(const RGB *src, int nsrc, + const uint8_t *pix, int npix, + int maxcol, + RGB *out, int *remap) +{ + int freq[256] = {0}; + int order[256]; + int i, j, nfree, nuniq; + + /* count pixel frequency per BMP palette entry */ + for (i = 0; i < npix; i++) + freq[pix[i]]++; + + /* sort BMP colors by frequency (descending) */ + for (i = 0; i < nsrc; i++) order[i] = i; + for (i = 1; i < nsrc; i++) { + int k = order[i], kf = freq[k]; + j = i - 1; + while (j >= 0 && freq[order[j]] < kf) { + order[j+1] = order[j]; + j--; + } + order[j+1] = k; + } + + /* count unique colors actually used */ + nuniq = 0; + for (i = 0; i < nsrc; i++) + if (freq[i] > 0) nuniq++; + + /* first 16 slots are AMIV UI */ + for (i = 0; i < 16 && i < maxcol; i++) + out[i] = amiv_pal[i]; + for (i = 16; i < maxcol; i++) + memset(&out[i], 0, sizeof(RGB)); + + nfree = maxcol - 16; + if (nfree < 0) nfree = 0; + + /* + * Case 1: enough free slots for all unique colors. + * Assign each unique BMP color its own pen, exact + * AMIV matches share the UI pen. + */ + if (nuniq <= nfree) { + int next = 16; + for (i = 0; i < nsrc; i++) { + if (freq[i] == 0) { + remap[i] = 0; + continue; + } + /* exact match to an AMIV pen? */ + int best = nearest(&src[i], amiv_pal, 16); + if (coldist(&src[i], &amiv_pal[best]) == 0) { + remap[i] = best; + } else { + remap[i] = next; + out[next] = src[i]; + next++; + } + } + return; + } + + /* + * Case 2: more unique colors than free slots. + * - Direct/near AMIV matches use UI pens. + * - Remaining slots filled by most-frequent colors. + * - Leftovers mapped to nearest in final palette. + */ + { + int next = 16; + int assigned[256]; + memset(assigned, 0, sizeof(assigned)); + + /* pass 1: exact/near AMIV matches */ + for (i = 0; i < nsrc; i++) { + if (freq[i] == 0) { + remap[i] = 0; + assigned[i] = 1; + continue; + } + int best = nearest(&src[i], amiv_pal, 16); + int d = coldist(&src[i], &amiv_pal[best]); + if (d < 200) { /* near match threshold */ + remap[i] = best; + assigned[i] = 1; + } + } + + /* pass 2: fill free slots with most-frequent + * unassigned colors (order[] is freq-sorted) */ + for (i = 0; i < nsrc && next < maxcol; i++) { + int idx = order[i]; + if (assigned[idx] || freq[idx] == 0) + continue; + remap[idx] = next; + out[next] = src[idx]; + assigned[idx] = 1; + next++; + } + + /* pass 3: map remaining to nearest in palette */ + for (i = 0; i < nsrc; i++) { + if (!assigned[i]) + remap[i] = nearest(&src[i], out, next); + } + } +} + +/* --------------------------------------------------------- */ +/* Main */ +/* --------------------------------------------------------- */ + +int +main(int argc, char **argv) +{ + FILE *bmpfp; + BMPFILEHEADER fhdr; + BMPINFOHEADER ihdr; + RGB palette[256]; + int ncolors, img_w, img_h, rowstride; + uint8_t *bmpdata, *pixels; + int ntiles, across, down; + int nplanes, maxcol; + int i, y; + RGB outpal[256]; + int remap[256]; + uint8_t *remapped; + uint8_t *plane_data[8]; + uint8_t cmap_rgb[256 * 3]; + int planesize; + + /* parse args */ + if (argc != 5 + || strcmp(argv[1], "-planes") != 0) { + fprintf(stderr, + "Usage: %s -planes N input.bmp output.iff\n", + argv[0]); + return 1; + } + nplanes = atoi(argv[2]); + if (nplanes < 1 || nplanes > 8) { + fprintf(stderr, "planes must be 1-8\n"); + return 1; + } + maxcol = 1 << nplanes; + + /* read BMP */ + bmpfp = fopen(argv[3], "rb"); + if (!bmpfp) { perror(argv[3]); return 1; } + + if (fread(&fhdr, sizeof(fhdr), 1, bmpfp) != 1 + || fread(&ihdr, sizeof(ihdr), 1, bmpfp) != 1) { + fprintf(stderr, "Failed to read BMP header\n"); + return 1; + } + if (fhdr.bfType != 0x4D42) { + fprintf(stderr, "Not a BMP file\n"); + return 1; + } + if (ihdr.biBitCount != 8) { + fprintf(stderr, + "Expected 8-bit BMP, got %d-bit\n", + ihdr.biBitCount); + return 1; + } + + img_w = ihdr.biWidth; + img_h = abs(ihdr.biHeight); + ncolors = ihdr.biClrUsed ? ihdr.biClrUsed : 256; + if (ncolors > 256) ncolors = 256; + + /* read palette (BMP stores BGRx) */ + { + uint8_t raw[256][4]; + if (fread(raw, 4, ncolors, bmpfp) + != (size_t)ncolors) { + fprintf(stderr, "Failed to read palette\n"); + return 1; + } + for (i = 0; i < ncolors; i++) { + palette[i].r = raw[i][2]; + palette[i].g = raw[i][1]; + palette[i].b = raw[i][0]; + } + } + + /* read pixel data */ + rowstride = (img_w + 3) & ~3; + bmpdata = malloc(rowstride * img_h); + fseek(bmpfp, fhdr.bfOffBits, SEEK_SET); + if (fread(bmpdata, 1, rowstride * img_h, bmpfp) + != (size_t)(rowstride * img_h)) { + fprintf(stderr, "Failed to read pixel data\n"); + return 1; + } + fclose(bmpfp); + + /* flip bottom-up to top-down */ + pixels = malloc(img_w * img_h); + if (ihdr.biHeight > 0) { + for (y = 0; y < img_h; y++) + memcpy(pixels + y * img_w, + bmpdata + (img_h-1-y) * rowstride, + img_w); + } else { + for (y = 0; y < img_h; y++) + memcpy(pixels + y * img_w, + bmpdata + y * rowstride, img_w); + } + free(bmpdata); + + across = img_w / TILE_X; + down = img_h / TILE_Y; + ntiles = across * down; + + /* build palette and remap pixels */ + build_palette(palette, ncolors, + pixels, img_w * img_h, + maxcol, outpal, remap); + + remapped = malloc(img_w * img_h); + for (i = 0; i < img_w * img_h; i++) + remapped[i] = (uint8_t)remap[pixels[i]]; + + /* convert to bitplanes */ + planesize = (img_w / 8) * img_h; + for (i = 0; i < nplanes; i++) + plane_data[i] = calloc(1, planesize); + + to_planes(remapped, img_w, img_h, + nplanes, plane_data); + + /* build CMAP */ + for (i = 0; i < maxcol; i++) { + cmap_rgb[i*3+0] = outpal[i].r; + cmap_rgb[i*3+1] = outpal[i].g; + cmap_rgb[i*3+2] = outpal[i].b; + } + + /* write IFF */ + iff_fp = fopen(argv[4], "wb"); + if (!iff_fp) { perror(argv[4]); return 1; } + + iff_write(nplanes, maxcol, cmap_rgb, + img_w, img_h, plane_data, + ntiles, across, down); + fclose(iff_fp); + + printf("%s: %dx%d, %d colors (%d planes), " + "%d tiles\n", + argv[4], img_w, img_h, + maxcol, nplanes, ntiles); + + for (i = 0; i < nplanes; i++) free(plane_data[i]); + free(remapped); + free(pixels); + return 0; +} diff --git a/outdated/sys/amiga/clipwin.c b/sys/amiga/clipwin.c similarity index 100% rename from outdated/sys/amiga/clipwin.c rename to sys/amiga/clipwin.c diff --git a/outdated/sys/amiga/colorwin.c b/sys/amiga/colorwin.c similarity index 100% rename from outdated/sys/amiga/colorwin.c rename to sys/amiga/colorwin.c diff --git a/outdated/sys/amiga/grave16.xpm b/sys/amiga/grave16.xpm similarity index 100% rename from outdated/sys/amiga/grave16.xpm rename to sys/amiga/grave16.xpm diff --git a/sys/amiga/nethack.cnf b/sys/amiga/nethack.cnf new file mode 100644 index 000000000..dad37d4d5 --- /dev/null +++ b/sys/amiga/nethack.cnf @@ -0,0 +1,44 @@ +# NetHack 3.7 Amiga Configuration +# +# For a full list of options, see the opthelp file or press '?' +# then 'o' during gameplay. + +# *** DISPLAY MODE *** +# +# Tile mode (graphical tiles, recommended): +OPTIONS=windowtype:amiv +# +# Text mode (uses hack.font line-drawing characters): +#OPTIONS=windowtype:amii +#OPTIONS=symset:AmigaFont + +# *** GENERAL OPTIONS *** +OPTIONS=time,showexp,lit_corridor +OPTIONS=boulder:0 +OPTIONS=autopickup,pickup_types:$"=/!?+ +OPTIONS=catname:Kaori + +# *** MENU COLORS *** +# Colour-code inventory items by BUC status and value. +OPTIONS=menucolors +MENUCOLOR=" blessed "=green +MENUCOLOR=" holy "=green +MENUCOLOR=" uncursed "=cyan +MENUCOLOR=" cursed "=red +MENUCOLOR=" unholy "=red +MENUCOLOR=" cursed .* (being worn)"=red&underline +MENUCOLOR=" cursed .* (wielded)"=red&underline +MENUCOLOR="loadstone"=red&underline +MENUCOLOR="gold piece"=brown +MENUCOLOR="worthless"=brown +MENUCOLOR="wand of wishing"=magenta +MENUCOLOR="magic lamp"=magenta +MENUCOLOR="magic marker"=magenta +MENUCOLOR="bag of holding"=magenta +MENUCOLOR="amulet of life saving"=magenta +MENUCOLOR="cloak of magic resistance"=magenta +MENUCOLOR="silver dragon scale"=cyan +MENUCOLOR="gray dragon scale"=cyan +MENUCOLOR="speed boots"=magenta +MENUCOLOR="luckstone"=green +MENUCOLOR="unicorn horn"=green diff --git a/outdated/sys/amiga/winamenu.c b/sys/amiga/winamenu.c similarity index 94% rename from outdated/sys/amiga/winamenu.c rename to sys/amiga/winamenu.c index 013e3c792..d391bdec4 100644 --- a/outdated/sys/amiga/winamenu.c +++ b/sys/amiga/winamenu.c @@ -15,14 +15,12 @@ /* Start building the text for a menu */ void -amii_start_menu(window, mbehavior) -register winid window; -unsigned long mbehavior UNUSED; - +amii_start_menu(winid window, unsigned long mbehavior UNUSED) { - register int i; - register struct amii_WinDesc *cw; - register amii_menu_item *mip; + int i; + struct amii_WinDesc *cw; + amii_menu_item *mip; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) @@ -64,17 +62,12 @@ unsigned long mbehavior UNUSED; /* Add a string to a menu */ void -amii_add_menu(window, glyph, id, ch, gch, attr, str, itemflags) -register winid window; -register int glyph; -register const anything *id; -register char ch; -register char gch; -register int attr; -register const char *str; -register unsigned int itemflags; +amii_add_menu(winid window, const glyph_info *glyphinfo, const anything *id, + char ch, char gch, int attr, int clr, + const char *str, unsigned int itemflags) { - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + boolean preselected = ((itemflags & MENU_ITEMFLAGS_SELECTED) != 0); amii_menu_item *mip; char buf[4 + BUFSZ]; @@ -90,7 +83,8 @@ register unsigned int itemflags; mip->identifier = *id; mip->selected = preselected; mip->attr = attr; - mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : glyph; + mip->color = clr; + mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : (glyphinfo ? glyphinfo->glyph : NO_GLYPH); mip->selector = 0; mip->gselector = gch; mip->count = -1; @@ -131,11 +125,10 @@ register unsigned int itemflags; /* Done building a menu. */ void -amii_end_menu(window, morestr) -register winid window; -register const char *morestr; +amii_end_menu(winid window, const char *morestr) { - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) @@ -151,8 +144,8 @@ register const char *morestr; mip = cw->menu.last; #endif any.a_void = 0; - amii_add_menu(window, NO_GLYPH, &any, 0, 0, ATR_NONE, morestr, - MENU_ITEMFLAGS_NONE); + amii_add_menu(window, (const glyph_info *) 0, &any, 0, 0, ATR_NONE, + NO_COLOR, morestr, MENU_ITEMFLAGS_NONE); #ifdef PROMPTFIRST /* Do some shuffling. Last first, push others one forward \ */ mip->next = NULL; @@ -178,13 +171,11 @@ register const char *morestr; /* Select something from the menu. */ int -amii_select_menu(window, how, mip) -register winid window; -register int how; -register menu_item **mip; +amii_select_menu(winid window, int how, menu_item **mip) { int cnt; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) @@ -199,7 +190,7 @@ register menu_item **mip; } amii_menu_item * -find_menu_item(register struct amii_WinDesc *cw, int idx) +find_menu_item(struct amii_WinDesc *cw, int idx) { amii_menu_item *mip; for (mip = cw->menu.items; idx > 0 && mip; mip = mip->next) @@ -209,11 +200,11 @@ find_menu_item(register struct amii_WinDesc *cw, int idx) } int -make_menu_items(register struct amii_WinDesc *cw, register menu_item **rmip) +make_menu_items(struct amii_WinDesc *cw, menu_item **rmip) { - register int idx = 0; - register amii_menu_item *mip; - register menu_item *mmip; + int idx = 0; + amii_menu_item *mip; + menu_item *mmip; for (mip = cw->menu.items; mip; mip = mip->next) { if (mip->selected) @@ -236,19 +227,17 @@ make_menu_items(register struct amii_WinDesc *cw, register menu_item **rmip) } int -DoMenuScroll(win, blocking, how, retmip) -int win, blocking, how; -menu_item **retmip; +DoMenuScroll(int win, int blocking, int how, menu_item **retmip) { amii_menu_item *amip; - register struct Window *w; - register struct NewWindow *nw; + struct Window *w; + struct NewWindow *nw; struct PropInfo *pip; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; struct IntuiMessage *imsg; struct Gadget *gd; - register int wheight, xsize, ysize, aredone = 0; - register int txwd, txh; + int wheight, xsize, ysize, aredone = 0; + int txwd, txh; long mics, secs, class, code; long oldmics = 0, oldsecs = 0; int aidx, oidx, topidx, hidden; @@ -819,7 +808,7 @@ menu_item **retmip; ++topidx; else break; - } else if (code = CTRL('U') + } else if (code == CTRL('U') || code == MENU_PREVIOUS_PAGE) { if (topidx > 0) --topidx; @@ -1007,11 +996,13 @@ menu_item **retmip; oldmics = mics; } else { amip = find_menu_item(cw, oidx); - amip->selected = 0; - amip->count = -1; - reset_counting = TRUE; - if (amip->canselect && amip->selector) - amip->str[SOFF + 2] = '-'; + if (amip) { + amip->selected = 0; + amip->count = -1; + reset_counting = TRUE; + if (amip->canselect && amip->selector) + amip->str[SOFF + 2] = '-'; + } } if (counting && amip->selected && amip->canselect && amip->selector) { @@ -1092,13 +1083,12 @@ menu_item **retmip; } void -ReDisplayData(win) -winid win; +ReDisplayData(winid win) { int totalvis; - register struct amii_WinDesc *cw; - register struct Window *w; - register struct Gadget *gd; + struct amii_WinDesc *cw; + struct Window *w; + struct Gadget *gd; unsigned long hidden, aidx, wheight; struct PropInfo *pip; @@ -1123,15 +1113,13 @@ winid win; } long -FindLine(win, line) -winid win; -int line; +FindLine(winid win, int line) { int txwd; - register char *t; - register struct amii_WinDesc *cw; - register struct Window *w; - register int i, disprow, len; + char *t; + struct amii_WinDesc *cw; + struct Window *w; + int i, disprow, len; int col = -1; if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) { @@ -1186,15 +1174,14 @@ int line; } long -CountLines(win) -winid win; +CountLines(winid win) { int txwd; amii_menu_item *mip; - register char *t; - register struct amii_WinDesc *cw; - register struct Window *w; - register int i, disprow, len; + char *t; + struct amii_WinDesc *cw; + struct Window *w; + int i, disprow, len; int col = -1; if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) { @@ -1250,17 +1237,15 @@ winid win; } void -DisplayData(win, start) -winid win; -int start; +DisplayData(winid win, int start) { int txwd; amii_menu_item *mip; - register char *t; - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; - register int i, disprow, len, wheight; + char *t; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; + int i, disprow, len, wheight; int whichcolor = -1; int col; @@ -1363,6 +1348,13 @@ int start; whichcolor = 2; } + /* Apply menucolor if set for this item */ + if (mip && mip->color != NO_COLOR && !(mip->selected)) { + extern const int foreg[]; + SetAPen(rp, foreg[mip->color]); + whichcolor = 0; /* force re-evaluation next item */ + } + /* Next line out, wrap if too long */ t = cw->data[i] + SOFF; @@ -1427,14 +1419,11 @@ int start; } void -SetPropInfo(win, gad, vis, total, top) -register struct Window *win; -register struct Gadget *gad; -register long vis, total, top; +SetPropInfo(struct Window *win, struct Gadget *gad, long vis, long total, long top) { long mflags; - register long hidden; - register int body, pot; + long hidden; + int body, pot; hidden = max(total - vis, 0); diff --git a/outdated/sys/amiga/winami.c b/sys/amiga/winami.c similarity index 94% rename from outdated/sys/amiga/winami.c rename to sys/amiga/winami.c index 4b7866346..7770a3547 100644 --- a/outdated/sys/amiga/winami.c +++ b/sys/amiga/winami.c @@ -39,7 +39,8 @@ long amii_scrnmode; * the intuition interface for the amiga... */ struct window_procs amii_procs = { - "amii", WC_COLOR | WC_HILITE_PET | WC_INVERSE, + WPID(amii), + WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ amii_init_nhwindows, @@ -48,7 +49,7 @@ struct window_procs amii_procs = { amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow, amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed, amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu, - amii_select_menu, genl_message_menu, amii_update_inventory, + amii_select_menu, genl_message_menu, amii_mark_synch, amii_wait_synch, #ifdef CLIPPING amii_cliparound, @@ -67,13 +68,16 @@ struct window_procs amii_procs = { genl_status_init, genl_status_finish, genl_status_enablefield, genl_status_update, genl_can_suspend_yes, + amii_update_inventory, + amii_ctrl_nhwindow, }; /* The view window layout uses the same function names so we can use * a shared library to allow the executable to be smaller. */ struct window_procs amiv_procs = { - "amitile", WC_COLOR | WC_HILITE_PET | WC_INVERSE, + WPID(amiv), + WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ amii_init_nhwindows, @@ -82,7 +86,7 @@ struct window_procs amiv_procs = { amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow, amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed, amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu, - amii_select_menu, genl_message_menu, amii_update_inventory, + amii_select_menu, genl_message_menu, amii_mark_synch, amii_wait_synch, #ifdef CLIPPING amii_cliparound, @@ -101,6 +105,8 @@ struct window_procs amiv_procs = { genl_status_init, genl_status_finish, genl_status_enablefield, genl_status_update, genl_can_suspend_yes, + amii_update_inventory, + amii_ctrl_nhwindow, }; unsigned short amii_initmap[AMII_MAXCOLORS]; @@ -428,7 +434,7 @@ struct NewScreen NewHackScreen = { 0, 0, WIDTH, SCREENHEIGHT, 3, 0, * init_sound_disp_gamewindows(). */ void -amii_askname() +amii_askname(void) { char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */ *plnametmp = 0; @@ -454,12 +460,12 @@ amii_askname() #if 0 /* New function at the bottom */ void -amii_player_selection() +amii_player_selection(void) { - register struct Window *cwin; - register struct IntuiMessage *imsg; - register int aredone = 0; - register struct Gadget *gd; + struct Window *cwin; + struct IntuiMessage *imsg; + int aredone = 0; + struct Gadget *gd; static int once = 0; long class, code; @@ -499,7 +505,7 @@ amii_player_selection() #ifdef INTUI_NEW_LOOK Type_NewWindowStructure1.Extension = wintags; Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; - fillhook.h_Entry = (ULONG(*)())LayerFillHook; + fillhook.h_Entry = (void *) &LayerFillHook; fillhook.h_Data = (void *)-2; fillhook.h_SubEntry = 0; #endif @@ -595,8 +601,7 @@ amii_player_selection() #include "NH:sys/amiga/randwin.c" void -RandomWindow( name ) - char *name; +RandomWindow(char *name) { struct MsgPort *tport; struct timerequest *trq; @@ -672,7 +677,7 @@ allocerr: #ifdef INTUI_NEW_LOOK Rnd_NewWindowStructure1.Extension = wintags; Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; - fillhook.h_Entry = (ULONG(*)())LayerFillHook; + fillhook.h_Entry = (void *) &LayerFillHook; fillhook.h_Data = (void *)-2; fillhook.h_SubEntry = 0; #endif @@ -762,10 +767,11 @@ amii_get_ext_cmd(void) #endif int colx; int bottom = 0; + struct Window *w; char obufp[100]; - register char *bufp = obufp; - register int c; + char *bufp = obufp; + int c; int com_index, oindex; int did_comp = 0; /* did successful completion? */ int sel = -1; @@ -787,7 +793,8 @@ amii_get_ext_cmd(void) id.a_char = *extcmdlist[i].ef_txt; sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt, extcmdlist[i].ef_desc); - amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0, + amii_add_menu(win, (const glyph_info *) 0, &id, + extcmdlist[i].ef_txt[0], 0, 0, NO_COLOR, buf, MENU_ITEMFLAGS_NONE); } @@ -848,8 +855,9 @@ amii_get_ext_cmd(void) id.a_char = extcmdlist[i].ef_txt[0]; sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt, extcmdlist[i].ef_desc); - amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, - 0, buf, MENU_ITEMFLAGS_NONE); + amii_add_menu(win, (const glyph_info *) 0, &id, + extcmdlist[i].ef_txt[0], 0, 0, NO_COLOR, + buf, MENU_ITEMFLAGS_NONE); } amii_end_menu(win, (char *) 0); @@ -941,10 +949,7 @@ amii_get_ext_cmd(void) } static int -put_ext_cmd(obufp, colx, cw, bottom) -char * obufp; -int colx, bottom; -struct amii_WinDesc *cw; +put_ext_cmd(char *obufp, int colx, struct amii_WinDesc *cw, int bottom) { struct Window *w = cw->win; char *t; @@ -989,10 +994,9 @@ struct amii_WinDesc *cw; /* Ask a question and get a response */ char -amii_yn_function(query, resp, def) -const char * query, *resp; -char def; +amii_yn_function(const char *query, const char *resp, char def) { + /* * Generic yes/no function. 'def' is the default (returned by space or * return; 'esc' returns 'q', or 'n', or the default, depending on @@ -1004,11 +1008,11 @@ char def; * are allowed); if it includes an , anything beyond that won't * be shown in the prompt to the user but will be acceptable as input. */ - register char q; + char q; char rtmp[40]; boolean digit_ok, allow_num; char prompt[BUFSZ]; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; if (cw = amii_wins[WIN_MESSAGE]) cw->disprows = 0; @@ -1138,16 +1142,15 @@ char def; } void -amii_display_file(fn, complain) -const char * fn; -boolean complain; +amii_display_file(const char *fn, boolean complain) { - register struct amii_WinDesc *cw; - register int win; - register dlb *fp; - register char *t; + struct amii_WinDesc *cw; + int win; + dlb *fp; + char *t; char buf[200]; + if (fn == NULL) panic("NULL file name in display_file()"); @@ -1194,12 +1197,11 @@ boolean complain; * are rendered in the up position by default. */ void -SetBorder(gd) -register struct Gadget * gd; +SetBorder(struct Gadget *gd) { - register struct Border *bp; - register short *sp; - register int i, inc = -1, dec = -1; + struct Border *bp; + short *sp; + int i, inc = -1, dec = -1; int borders = 6; int hipen = sysflags.amii_dripens[SHINEPEN], shadowpen = sysflags.amii_dripens[SHADOWPEN]; @@ -1337,7 +1339,7 @@ register struct Gadget * gd; /* Following function copied from wintty.c; Modified slightly to fit amiga needs */ void -amii_player_selection() +amii_player_selection(void) { int i, k, n; char pick4u = 'n', thisch, lastch = 0; @@ -1346,6 +1348,7 @@ amii_player_selection() anything any; menu_item *selected = 0; + rigid_role_checks(); /* Should we randomly pick for the player? */ @@ -1424,8 +1427,8 @@ amii_player_selection() } else Strcpy(rolenamebuf, roles[i].name.m); } - add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE, - an(rolenamebuf), MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, thisch, 0, ATR_NONE, + NO_COLOR, an(rolenamebuf), MENU_ITEMFLAGS_NONE); lastch = thisch; } } @@ -1433,11 +1436,11 @@ amii_player_selection() flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrole(FALSE) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick a role for your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); @@ -1498,19 +1501,19 @@ amii_player_selection() if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) { any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0, - ATR_NONE, races[i].noun, + add_menu(win, &nul_glyphinfo, &any, races[i].noun[0], 0, + ATR_NONE, NO_COLOR, races[i].noun, MENU_ITEMFLAGS_NONE); } any.a_int = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrace(flags.initrole) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the race of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); @@ -1571,18 +1574,19 @@ amii_player_selection() if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) { any.a_int = i + 1; - add_menu(win, NO_GLYPH, &any, genders[i].adj[0], 0, - ATR_NONE, genders[i].adj, MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, genders[i].adj[0], 0, + ATR_NONE, NO_COLOR, genders[i].adj, + MENU_ITEMFLAGS_NONE); } any.a_int = pick_gend(flags.initrole, flags.initrace, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randgend(flags.initrole, flags.initrace) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the gender of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); @@ -1642,18 +1646,19 @@ amii_player_selection() if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) { any.a_int = i + 1; - add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0, - ATR_NONE, aligns[i].adj, MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, aligns[i].adj[0], 0, + ATR_NONE, NO_COLOR, aligns[i].adj, + MENU_ITEMFLAGS_NONE); } any.a_int = pick_align(flags.initrole, flags.initrace, flags.initgend, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randalign(flags.initrole, flags.initrace) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the alignment of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); diff --git a/outdated/sys/amiga/winami.p b/sys/amiga/winami.p similarity index 87% rename from outdated/sys/amiga/winami.p rename to sys/amiga/winami.p index 2e26cfb10..dfb588177 100644 --- a/outdated/sys/amiga/winami.p +++ b/sys/amiga/winami.p @@ -5,10 +5,10 @@ void amii_raw_print(const char *); void amii_raw_print_bold(const char *); void amii_start_menu(winid , unsigned long ); -void amii_add_menu(winid , char , int , const char *, unsigned int); +void amii_add_menu(winid, const glyph_info *, const anything *, char, char, int, int, const char *, unsigned int); void amii_end_menu(winid , char , const char * , const char *); char amii_select_menu(winid ); -void amii_update_inventory (void); +void amii_update_inventory(int); void amii_mark_synch (void); void amii_wait_synch (void); void amii_setclipped (void); @@ -27,7 +27,7 @@ void amii_putstr(winid , int , const char *); void amii_putsym(winid , int , int , CHAR_P ); void amii_clear_nhwindow(winid ); void amii_exit_nhwindows(const char *); -int amii_nh_poskey(int * , int * , int *); +int amii_nh_poskey(coordxy *, coordxy *, int *); int amii_nhgetch (void); void amii_get_nh_event (void); void amii_remember_topl (void); @@ -35,7 +35,7 @@ int amii_doprev_message (void); void amii_display_nhwindow(winid , boolean ); void amii_display_file(const char * , boolean ); void amii_curs(winid , int , int ); -void amii_print_glyph(winid , coordxy , coordxy , int, int ); +void amii_print_glyph(winid, coordxy, coordxy, const glyph_info *, const glyph_info *); void DoMenuScroll(int , int ); void DisplayData(int , int , int ); void SetPropInfo(struct Window * , struct Gadget * , long , long , long ); diff --git a/outdated/sys/amiga/winchar.c b/sys/amiga/winchar.c similarity index 78% rename from outdated/sys/amiga/winchar.c rename to sys/amiga/winchar.c index e4e56b8a2..75c35c87b 100644 --- a/outdated/sys/amiga/winchar.c +++ b/sys/amiga/winchar.c @@ -41,7 +41,8 @@ int main(int, char **); struct BitMap *MyAllocBitMap(int, int, int, long); void MyFreeBitMap(struct BitMap *); -void FreeImageFiles(char **, struct BitMap **); +BitMapHeader ReadImageFile(const char *, struct BitMap **); +void FreeImageFile(struct BitMap **); void amiv_flush_glyph_buffer(struct Window *); void amiv_lprint_glyph(winid, int, int); void amii_lprint_glyph(winid, int, int); @@ -91,17 +92,9 @@ extern int maxmontile, maxobjtile, maxothtile; /* from tile.c */ struct PDAT pictdata; -#define NUMTILEIMAGES 3 -char *tileimages[] = { -#define TBLMONTILE 0 - "NetHack:tiles/monsters.iff", -#define TBLOBJTILE 1 - "NetHack:tiles/objects.iff", -#define TBLOTHTILE 2 - "NetHack:tiles/other.iff", 0, -}; - -struct BitMap *ifftimg[NUMTILEIMAGES], *tile; +/* Single tile image file, set at runtime by amii_init_nhwindows */ +char *tilefile; +struct BitMap *tileimg, *tile; #ifdef TESTING short pens[NUMDRIPENS] = { 8, 3, 15, 0, 15, 7, 7, 8, 0 }; @@ -146,7 +139,7 @@ main(int argc, char **argv) x = x % IMGCOLUMNS; dx = i % (IMGCOLUMNS * 2); dy = i / (IMGCOLUMNS * 2); - BltBitMapRastPort(ifftimg[tbl], x * pictdata.xsize, + BltBitMapRastPort(tileimg, x * pictdata.xsize, y * pictdata.ysize, w->RPort, w->BorderLeft + 1 + dx * pictdata.xsize, w->BorderTop + 1 + dy * pictdata.ysize, @@ -176,175 +169,112 @@ main(int argc, char **argv) CloseScreen(scr); } - FreeImageFiles(tileimages, ifftimg); + FreeTileImageFiles(); return (0); } #endif +/* + * Read a single BMAP IFF file into a BitMap. + * Returns the BitMapHeader; *bmp receives the bitmap. + * Caller frees via FreeImageFile(). + */ BitMapHeader -ReadTileImageFiles() +ReadImageFile(const char *filename, struct BitMap **bmp) { - char *errstr = NULL; - BitMapHeader ret = ReadImageFiles(tileimages, ifftimg, &errstr); - if (errstr) { - panic(errstr); - } - return ret; -} - -BitMapHeader -ReadImageFiles(char **filenames, struct BitMap **iffimg, char **errstrp) -{ - BitMapHeader *bmhd = NULL, bmhds; - unsigned char *cmap; - extern int errno; - register int i, j; + BitMapHeader *bmhd, bmhds; + int j, np; struct IFFHandle *iff; struct StoredProperty *prop; IFFParseBase = OpenLibrary("iffparse.library", 0L); - if (!IFFParseBase) { - *errstrp = "No iffparse.library"; - return bmhds; + if (!IFFParseBase) + panic("No iffparse.library"); + + iff = AllocIFF(); + if (!iff) + panic("can't start IFF processing"); + + iff->iff_Stream = Open(filename, MODE_OLDFILE); + if (iff->iff_Stream == 0) + panic("Can't open %s", filename); + + InitIFFasDOS(iff); + OpenIFF(iff, IFFF_READ); + PropChunk(iff, ID_BMAP, ID_BMHD); + PropChunk(iff, ID_BMAP, ID_CMAP); + PropChunk(iff, ID_BMAP, ID_PDAT); + StopChunk(iff, ID_BMAP, ID_PLNE); + if ((j = ParseIFF(iff, IFFPARSE_SCAN)) != 0) + panic("ParseIFF failed on %s, code %d", + filename, j); + + prop = FindProp(iff, ID_BMAP, ID_BMHD); + if (!prop) + panic("No BMHD chunk in %s", filename); + bmhd = (BitMapHeader *) prop->sp_Data; + np = bmhd->nPlanes; + + /* Load CMAP into palette arrays if present */ + prop = FindProp(iff, ID_BMAP, ID_CMAP); + if (prop) { + unsigned char *cmap = prop->sp_Data; + for (j = 0; j < (1L << np) * 3; j += 3) { + amii_initmap[j / 3] = + amiv_init_map[j / 3] = + ((cmap[j+0] >> 4) << 8) + | ((cmap[j+1] >> 4) << 4) + | (cmap[j+2] >> 4); + } } - /* - for( i = 0; filenames[i]; ++i ) - memset( iffimg[i], 0, sizeof( struct BitMap ) ); - */ - for (i = 0; filenames[i]; ++i) { - iff = AllocIFF(); - if (!iff) { - FreeImageFiles(filenames, iffimg); - *errstrp = "can't start IFF processing"; - return bmhds; - } - iff->iff_Stream = Open(filenames[i], MODE_OLDFILE); - if (iff->iff_Stream == 0) { - char *buf = malloc(100 + strlen(filenames[i])); - FreeImageFiles(filenames, iffimg); - sprintf(buf, "Can't open %s: %s", filenames[i], strerror(errno)); - *errstrp = buf; - return bmhds; - } - InitIFFasDOS(iff); - OpenIFF(iff, IFFF_READ); - PropChunk(iff, ID_BMAP, ID_BMHD); - PropChunk(iff, ID_BMAP, ID_CMAP); - PropChunk(iff, ID_BMAP, ID_CAMG); - PropChunk(iff, ID_BMAP, ID_PDAT); - StopChunk(iff, ID_BMAP, ID_PLNE); - if ((j = ParseIFF(iff, IFFPARSE_SCAN)) != 0) { - char *buf = malloc(100); - FreeImageFiles(filenames, iffimg); - sprintf(buf, "ParseIFF failed for image %d, failure code: %d", i, - j); - *errstrp = buf; - return bmhds; - } + /* Load PDAT if present */ + prop = FindProp(iff, ID_BMAP, ID_PDAT); + if (prop) + pictdata = *(struct PDAT *) prop->sp_Data; - if (prop = FindProp(iff, ID_BMAP, ID_BMHD)) { - bmhd = (BitMapHeader *) prop->sp_Data; - } else { - FreeImageFiles(filenames, iffimg); - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - *errstrp = "No BMHD CHUNK in file"; - return bmhds; - } + *bmp = MyAllocBitMap(bmhd->w, bmhd->h, + np, MEMF_CHIP | MEMF_CLEAR); + if (!*bmp) + panic("Can't allocate bitmap for %s", filename); - if (prop = FindProp(iff, ID_BMAP, ID_CMAP)) { - cmap = prop->sp_Data; - for (j = 0; j < (1L << bmhd->nPlanes) * 3; j += 3) { -#if 0 - /* Some day we will want to use the larger palette - * resolution available under v39 and later. i.e. - * 32 instead of 12 bits of color. Ususally this - * just means shifting the color left by 16-20 bits - * depending on what intensity looks best. Experience - * says that the higher values are better intensities. - * - * For now though we won't do this. The color table - * structure is incompatible with earlier versions of - * intuition. We would have to do some funny things - * to make 3*AMII_MAXCOLORS longs work like 3*AMII_MAXCOLORS - * UWORD's at run time... A union would help, but... - */ - if( IntuitionBase->LibNode.lib_Version >= 39 ) - { - /* 8 bits of color, so shift to left end. */ - amiv_init_map[ j+0 ] = cmap[j+0]<<24; - amiv_init_map[ j+1 ] = cmap[j+1]<<24; - amiv_init_map[ j+2 ] = cmap[j+2]<<24; - } - else -#endif - { -/* We can only use 4 bits of the 8 that are stored in the - * cmap, so mask them and then shift them into position - * for the UWORD value to store. - */ -#ifndef TESTING - amii_initmap[j / 3] = amiv_init_map[j / 3] = - ((cmap[j + 0] >> 4) << 8) | ((cmap[j + 1] >> 4) << 4) - | (cmap[j + 2] >> 4); -#endif - } - } - } else { - FreeImageFiles(filenames, iffimg); - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - *errstrp = "No CMAP CHUNK in file"; - return bmhds; - } + for (j = 0; j < np; j++) + ReadChunkBytes(iff, (*bmp)->Planes[j], + RASSIZE(bmhd->w, bmhd->h)); - if (prop = FindProp(iff, ID_BMAP, ID_PDAT)) { - struct PDAT *pp; - - pp = (struct PDAT *) prop->sp_Data; - pictdata = *pp; - } else { - FreeImageFiles(filenames, iffimg); - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - *errstrp = "No PDAT CHUNK in file"; - return bmhds; - } - - iffimg[i] = MyAllocBitMap(bmhd->w, bmhd->h, - pictdata.nplanes + amii_extraplanes, - MEMF_CHIP | MEMF_CLEAR); - if (iffimg[i] == NULL) { - char *buf = malloc(80); - FreeImageFiles(filenames, iffimg); - sprintf(buf, "Can't allocate bitmap for image %d\n", i); - *errstrp = buf; - return bmhds; - } - for (j = 0; j < pictdata.nplanes + amii_extraplanes; ++j) { - ReadChunkBytes(iff, iffimg[i]->Planes[j], - RASSIZE(bmhd->w, bmhd->h)); - } - bmhds = *bmhd; - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - } + bmhds = *bmhd; + CloseIFF(iff); + Close(iff->iff_Stream); + FreeIFF(iff); CloseLibrary(IFFParseBase); - tile = MyAllocBitMap(pictdata.xsize, pictdata.ysize, - pictdata.nplanes + amii_extraplanes, - MEMF_CHIP | MEMF_CLEAR); - if (tile == NULL) { - FreeImageFiles(filenames, iffimg); - *errstrp = "Can't allocate tile bitmap for scaling"; + return bmhds; +} + +void +FreeImageFile(struct BitMap **bmp) +{ + if (*bmp) { + MyFreeBitMap(*bmp); + *bmp = NULL; } - return (bmhds); +} + +BitMapHeader +ReadTileImageFiles(void) +{ + BitMapHeader bmhds; + + bmhds = ReadImageFile(tilefile, &tileimg); + + tile = MyAllocBitMap(pictdata.xsize, pictdata.ysize, + pictdata.nplanes + amii_extraplanes, + MEMF_CHIP | MEMF_CLEAR); + if (!tile) + panic("Can't allocate tile temp bitmap"); + + return bmhds; } struct MyBitMap { @@ -401,8 +331,7 @@ MyFreeBitMap(struct BitMap *bmp) #ifdef TESTING void -panic(s, a1, a2, a3, a4) -char *s; +panic(char *s, long a1, long a2, long a3, long a4) { printf(s, a1, a2, a3, a4); putchar('\n'); @@ -420,24 +349,10 @@ alloc(unsigned int x) #endif void -FreeTileImageFiles() +FreeTileImageFiles(void) { - FreeImageFiles(tileimages, ifftimg); -} - -void -FreeImageFiles(char **filenames, struct BitMap **img) -{ - register int i; - - for (i = 0; filenames[i]; ++i) { - if (img[i]) - MyFreeBitMap(img[i]); - } - - /* REALLY ugly hack alert! */ - if (tile && img == ifftimg) - MyFreeBitMap(tile); + FreeImageFile(&tileimg); + FreeImageFile(&tile); } #ifndef TESTING @@ -456,8 +371,7 @@ struct amiv_glyph_node amiv_g_nodes[NUMBER_GLYPH_NODES]; static char amiv_glyph_buffer[GLYPH_BUFFER_SIZE]; void -flush_glyph_buffer(vw) -struct Window *vw; +flush_glyph_buffer(struct Window *vw) { if (WINVERS_AMIV) amiv_flush_glyph_buffer(vw); @@ -469,8 +383,7 @@ struct Window *vw; * Routine to flush whatever is buffered */ void -amiv_flush_glyph_buffer(vw) -struct Window *vw; +amiv_flush_glyph_buffer(struct Window *vw) { #if !defined(DISPMAP) || defined(OPT_DISPMAP) int xsize, ysize, x, y; @@ -481,7 +394,7 @@ struct Window *vw; struct BitMap *imgbm = 0, *bm = 0; int i, k; int scaling_needed; - register struct RastPort *rp = vw->RPort; + struct RastPort *rp = vw->RPort; #endif /* If nothing is buffered, return before we do anything */ @@ -577,7 +490,7 @@ struct Window *vw; /* Go ahead and start dumping the stuff */ for (i = 0; i < glyph_node_index; ++i) { /* Do it */ - register int offx, offy, j; + int offx, offy, j; struct BitMap *nodebm = amiv_g_nodes[i].bitmap; /* Get the unclipped coordinates */ @@ -596,10 +509,10 @@ struct Window *vw; * this code is generalized to handle any size tile * image... */ - memcpy(tile->Planes[j] + ((k * pictdata.ysize) / 8), + memcpy(tile->Planes[j] + k * tile->BytesPerRow, nodebm->Planes[j] + offx + offy + (nodebm->BytesPerRow * k), - pictdata.ysize / 8); + pictdata.xsize / 8); } } @@ -648,41 +561,30 @@ struct Window *vw; * Glyph buffering routine. Called instead of WindowPuts(). */ void -amiv_lprint_glyph(window, color_index, glyph) -winid window; -int color_index, glyph; +amiv_lprint_glyph(winid window, int color_index, int glyph) { int base; struct amii_WinDesc *cw; struct Window *w; int curx; int cury; - int tbl, icon; - register int xoff, yoff; + int icon; + int xoff, yoff; - /* Get the real icon index */ - if (glyph != NO_GLYPH) - icon = GlyphToIcon(glyph); + /* Skip NO_GLYPH — nothing to draw */ + if (glyph == NO_GLYPH) + return; + + icon = GlyphToIcon(glyph); if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL) panic("bad winid in amiv_lprint_glyph: %d", window); w = cw->win; - if (glyph != NO_GLYPH && glyph < 10000) { - /* decide on which image has the needed picture */ - if (icon <= MAXMONTILE) { - tbl = TBLMONTILE; - base = 0; - } else if (icon <= MAXOBJTILE) { - tbl = TBLOBJTILE; - base = MAXMONTILE + 1; - } else if (icon <= MAXOTHTILE) { - tbl = TBLOTHTILE; - base = MAXOBJTILE + 1; - } else - panic("Bad icon #%d, glyph #%d, only %d icons known\n", icon, - glyph, MAXOTHTILE); + if (glyph < 10000) { + if (icon >= pictdata.npics) + icon = 0; /* fallback for out-of-range */ /* Get the relative offset in the page */ @@ -748,11 +650,11 @@ int color_index, glyph; amiv_g_nodes[glyph_node_index].odstx = cw->curx; amiv_g_nodes[glyph_node_index].srcx = xoff; amiv_g_nodes[glyph_node_index].srcy = yoff; - amiv_g_nodes[glyph_node_index].bitmap = ifftimg[tbl]; + amiv_g_nodes[glyph_node_index].bitmap = tileimg; ++glyph_node_index; } else { /* Do it */ - register int j, k, x, y, apen; + int j, k, x, y, apen; struct RastPort *rp = w->RPort; x = rp->cp_x - pictdata.xsize - 3; #ifdef OPT_DISPMAP @@ -770,17 +672,17 @@ int color_index, glyph; y = rp->cp_y - pictdata.ysize + 1; if (glyph != NO_GLYPH) { - struct BitMap *bm = ifftimg[tbl]; + struct BitMap *bm = tileimg; /* 8 bits per byte */ xoff /= 8; yoff *= bm->BytesPerRow; for (j = 0; j < pictdata.nplanes; ++j) { for (k = 0; k < pictdata.ysize; ++k) { - memcpy(tile->Planes[j] + ((k * pictdata.ysize) / 8), + memcpy(tile->Planes[j] + k * tile->BytesPerRow, bm->Planes[j] + xoff + yoff + (bm->BytesPerRow * k), - pictdata.ysize / 8); + pictdata.xsize / 8); } } @@ -824,8 +726,7 @@ static int usecolor; */ void -amiv_start_glyphout(window) -winid window; +amiv_start_glyphout(winid window) { struct amii_WinDesc *cw; struct Window *w; @@ -860,8 +761,7 @@ winid window; * General cleanup routine -- flushes and restores cursor */ void -amii_end_glyphout(window) -winid window; +amii_end_glyphout(winid window) { struct amii_WinDesc *cw; struct Window *w; @@ -891,7 +791,7 @@ winid window; Move(w->RPort, xsave, ysave); } -static maze_type = COL_MAZE_BRICK; +static int maze_type = COL_MAZE_BRICK; void SetMazeType(MazeType t) @@ -987,11 +887,10 @@ int backg[AMII_MAXCOLORS] = { * Routine to simply flush whatever is buffered */ void -amii_flush_glyph_buffer(w) -struct Window *w; +amii_flush_glyph_buffer(struct Window *w) { short i, x, y; - register struct RastPort *rp = w->RPort; + struct RastPort *rp = w->RPort; /* If nothing is buffered, return before we do anything */ if (glyph_node_index == 0) @@ -1013,6 +912,10 @@ struct Window *w; + rp->TxBaseline + 1; x = amii_g_nodes[i].x * rp->TxWidth + w->BorderLeft; + /* Skip if pixel coordinates are outside window */ + if (x < 0 || y < 0 || y >= w->Height || x >= w->Width) + continue; + /* Move pens to correct location */ Move(rp, (long) x, (long) y); @@ -1029,9 +932,7 @@ struct Window *w; glyph_node_index = glyph_buffer_index = 0; } void -amiga_print_glyph(window, color_index, glyph) -winid window; -int color_index, glyph; +amiga_print_glyph(winid window, int color_index, int glyph) { if (WINVERS_AMIV) amiv_lprint_glyph(window, color_index, glyph); @@ -1043,9 +944,7 @@ int color_index, glyph; * Glyph buffering routine. Called instead of WindowPuts(). */ void -amii_lprint_glyph(window, color_index, glyph) -winid window; -int color_index, glyph; +amii_lprint_glyph(winid window, int color_index, int glyph) { int fg_color, bg_color; struct amii_WinDesc *cw; @@ -1120,8 +1019,7 @@ static int usecolor; */ void -amii_start_glyphout(window) -winid window; +amii_start_glyphout(winid window) { struct amii_WinDesc *cw; struct Window *w; @@ -1195,7 +1093,7 @@ amii_end_glyphout(window) #ifdef OPT_DISPMAP /* don't use dispmap unless x & y are 8,16,24,32,48 and equal */ void -dispmap_sanity() +dispmap_sanity(void) { if (mxsize != mysize || dispmap_sanity1(mxsize) || dispmap_sanity1(mysize)) { @@ -1203,11 +1101,10 @@ dispmap_sanity() } } int -dispmap_sanity1(x) -int x; +dispmap_sanity1(int x) { static unsigned char valid[] = { 8, 16, 24, 32, 48, 0 }; - return !!strchr(valid, x); + return !strchr((char *)valid, x); } #endif /* OPT_DISPMAP */ #endif /* TESTING */ diff --git a/outdated/sys/amiga/windefs.h b/sys/amiga/windefs.h similarity index 98% rename from outdated/sys/amiga/windefs.h rename to sys/amiga/windefs.h index 9e59da82f..cb6cbd3db 100644 --- a/outdated/sys/amiga/windefs.h +++ b/sys/amiga/windefs.h @@ -112,7 +112,7 @@ CLIPPING must be defined for the AMIGA version #endif #define WINVERS_AMII (strcmp("amii", windowprocs.name) == 0) -#define WINVERS_AMIV (strcmp("amitile", windowprocs.name) == 0) +#define WINVERS_AMIV (strcmp("amiv", windowprocs.name) == 0) #define WINVERS_AMIT (strcmp("amitty", windowprocs.name) == 0) /* cw->data[x] contains 2 characters worth of special information. These @@ -196,3 +196,4 @@ struct PDAT #undef MAXCOLORS #define MAXCOLORS 256 + diff --git a/outdated/sys/amiga/winext.h b/sys/amiga/winext.h similarity index 100% rename from outdated/sys/amiga/winext.h rename to sys/amiga/winext.h diff --git a/outdated/sys/amiga/winfuncs.c b/sys/amiga/winfuncs.c similarity index 86% rename from outdated/sys/amiga/winfuncs.c rename to sys/amiga/winfuncs.c index 9907ce1c6..7d451a665 100644 --- a/outdated/sys/amiga/winfuncs.c +++ b/sys/amiga/winfuncs.c @@ -14,7 +14,6 @@ #endif #include "patchlevel.h" -#include "date.h" extern struct TagItem scrntags[]; #ifndef CROSS_TO_AMIGA @@ -40,6 +39,11 @@ int xclipbord = 4, yclipbord = 2; #endif int mxsize, mysize; + +/* Track the last level we centered the clipping viewport on, so that + both amii_clear_nhwindow (pre-docrt centering) and amii_cliparound + (scroll/pan during play) can detect level changes. */ +static d_level clip_saved_level = { 127, 127 }; /* XXX */ struct Rectangle amii_oldover; struct Rectangle amii_oldmsg; @@ -58,8 +62,7 @@ int amii_otherBPen; long amii_libvers = LIBRARY_FONT_VERSION; void -ami_wininit_data(dir) -int dir; +ami_wininit_data(int dir) { extern unsigned short amii_init_map[AMII_MAXCOLORS]; extern unsigned short amiv_init_map[AMII_MAXCOLORS]; @@ -150,12 +153,13 @@ struct TagItem wintags[] = { }; #endif -void amii_destroy_nhwindow(win) /* just hide */ -register winid win; +void +amii_destroy_nhwindow(winid win) /* just hide */ { int i; int type; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (win == WIN_ERR || (cw = amii_wins[win]) == NULL) { panic(winpanicstr, win, "destroy_nhwindow"); @@ -260,26 +264,37 @@ PPC_LayerFillHook(void) struct RastPort *rp = (struct RastPort *) REG_A2; struct FillParams *fp = (struct FillParams *) REG_A1; #else +/* Assembly trampoline: Intuition calls LayerFillHook with arguments + in registers a0 (hook), a1 (fillparams), a2 (rastport). + Push them onto the stack and call the C implementation. */ +__asm( +" .globl _LayerFillHook\n" +"_LayerFillHook:\n" +" move.l a1,-(sp)\n" +" move.l a2,-(sp)\n" +" move.l a0,-(sp)\n" +" jsr _LayerFillHook_impl\n" +" lea 12(sp),sp\n" +" rts\n" +); void -LayerFillHook(void) +LayerFillHook_impl(struct Hook *hk, struct RastPort *rp, + struct FillParams *fp) { - register struct Hook *hk asm("a0"); - register struct RastPort *rp asm("a2"); - register struct FillParams *fp asm("a1"); #endif #else void #ifndef _DCC __interrupt #endif - __saveds __asm LayerFillHook(register __a0 struct Hook *hk, - register __a2 struct RastPort *rp, - register __a1 struct FillParams *fp) + __saveds __asm LayerFillHook(__a0 struct Hook *hk, + __a2 struct RastPort *rp, + __a1 struct FillParams *fp) { #endif - register long x, y, xmax, ymax; - register int apen; + long x, y, xmax, ymax; + int apen; struct RastPort rptmp; memcpy(&rptmp, rp, sizeof(struct RastPort)); @@ -321,15 +336,17 @@ void } #endif -amii_create_nhwindow(type) register int type; +winid +amii_create_nhwindow(int type) { - register struct Window *w = NULL; - register struct NewWindow *nw = NULL; - register struct amii_WinDesc *wd = NULL; + struct Window *w = NULL; + struct NewWindow *nw = NULL; + struct amii_WinDesc *wd = NULL; struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL; - register int newid; + int newid; int maph, stath, scrfontysize; + scrfontysize = HackScreen->Font->ta_YSize; /* @@ -563,11 +580,7 @@ amii_create_nhwindow(type) register int type; case NHW_OVER: case NHW_MAP: if (wd) { -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) type; fillhook.h_SubEntry = 0; wd->hook = alloc(sizeof(fillhook)); @@ -665,6 +678,10 @@ amii_create_nhwindow(type) register int type; / w->RPort->TxHeight; wd->cols = (w->Width - w->BorderLeft - w->BorderRight - 2) / w->RPort->TxWidth; + /* Map window uses y+2 offset in amii_print_glyph, so cury + values go up to ROWNO+2. Ensure rows accommodates this. */ + if (type == NHW_MAP && wd->rows < ROWNO + 3) + wd->rows = ROWNO + 3; } /* Okay, now do the individual type initialization */ @@ -736,7 +753,9 @@ amii_create_nhwindow(type) register int type; */ wd->data = (char **) alloc(3 * sizeof(char *)); wd->data[0] = (char *) alloc(wd->cols + 10); + wd->data[0][0] = '\0'; wd->data[1] = (char *) alloc(wd->cols + 10); + wd->data[1][0] = '\0'; wd->data[2] = NULL; break; @@ -771,7 +790,7 @@ amii_create_nhwindow(type) register int type; SetMenuStrip(w, MenuStrip); /* Make our requesters come to our screen */ { - register struct Process *myProcess = + struct Process *myProcess = (struct Process *) FindTask(NULL); pr_WindowPtr = (struct Window *) (myProcess->pr_WindowPtr); myProcess->pr_WindowPtr = (APTR) w; @@ -787,17 +806,7 @@ amii_create_nhwindow(type) register int type; Abort(AG_OpenDev | AO_ConsoleDev); } - ConsoleDevice = -#ifndef CROSS_TO_AMIGA - (struct Library *) -#else - (struct Device * -# ifdef __CONSTLIBBASEDECL__ - __CONSTLIBBASEDECL__ -# endif /* __CONSTLIBBASEDECL__ */ - ) -#endif - ConsoleIO.io_Device; + ConsoleDevice = (struct Device *) ConsoleIO.io_Device; KbdBuffered = 0; #ifdef HACKFONT @@ -831,12 +840,23 @@ PPC_SM_Filter(void) ULONG modeID = (ULONG) REG_A1; struct ScreenModeRequester *smr = (struct ScreenModeRequester *) REG_A2; #else +/* Assembly trampoline for SM_Filter hook callback. + SM_Filter is the asm entry point; SM_Filter_impl is the C body. */ +extern void SM_Filter(void); +__asm( +" .globl _SM_Filter\n" +"_SM_Filter:\n" +" move.l a2,-(sp)\n" +" move.l a1,-(sp)\n" +" move.l a0,-(sp)\n" +" jsr _SM_Filter_impl\n" +" lea 12(sp),sp\n" +" rts\n" +); int -SM_Filter(void) +SM_Filter_impl(struct Hook *hk, ULONG modeID, + struct ScreenModeRequester *smr) { - register struct Hook *hk asm("a0"); - register ULONG modeID asm("a1"); - register struct ScreenModeRequester *smr asm("a2"); #endif #else int @@ -844,8 +864,8 @@ int __interrupt #endif __saveds __asm SM_Filter( - register __a0 struct Hook *hk, register __a1 ULONG modeID, - register __a2 struct ScreenModeRequester *smr) + __a0 struct Hook *hk, __a1 ULONG modeID, + __a2 struct ScreenModeRequester *smr) { #endif struct DimensionInfo dims; @@ -869,14 +889,13 @@ int /* Initialize the windowing environment */ void -amii_init_nhwindows(argcp, argv) -int *argcp; -char **argv; +amii_init_nhwindows(int *argcp, char **argv) { int i; struct Screen *wbscr; int forcenobig = 0; + if (HackScreen) panic("init_nhwindows() called twice", 0); @@ -1192,9 +1211,16 @@ char **argv; } #endif - if (WINVERS_AMIV) + if (WINVERS_AMIV) { + extern char *tilefile; + if (amii_numcolors >= 32) { + tilefile = "NetHack:tiles/tiles32.iff"; + amii_numcolors = 32; + } else { + tilefile = "NetHack:tiles/tiles16.iff"; + } amii_bmhd = ReadTileImageFiles(); - else + } else memcpy(amii_initmap, amii_init_map, sizeof(amii_initmap)); memcpy(sysflags.amii_curmap, amii_initmap, sizeof(sysflags.amii_curmap)); @@ -1361,11 +1387,11 @@ amii_setdrawpens(struct Window *w, int type) /* Clear the indicated window */ void -amii_clear_nhwindow(win) -register winid win; +amii_clear_nhwindow(winid win) { - register struct amii_WinDesc *cw; - register struct Window *w; + struct amii_WinDesc *cw; + struct Window *w; + if (reclip == 2) return; @@ -1394,6 +1420,40 @@ register winid win; amii_setfillpens(w, cw->type); SetDrMd(w->RPort, JAM2); +#ifdef CLIPPING + /* When clearing the map for a full redraw (docrt/cls), center the + clipping viewport on the player BEFORE the map is redrawn. + Without this, the first docrt() after a level change or new game + draws with stale clip coordinates (typically 0,0), leaving the + player off-screen until their first move triggers amii_cliparound. */ + if (cw->type == NHW_MAP && clipping && u.ux + && !on_level(&u.uz, &clip_saved_level)) { + int COx, LIx; + struct RastPort *rp = w->RPort; + + if (Is_rogue_level(&u.uz)) { + COx = (w->Width - w->BorderLeft - w->BorderRight) / rp->TxWidth; + LIx = (w->Height - w->BorderTop - w->BorderBottom) / rp->TxHeight; + } else { + COx = CO; + LIx = LI; + } + clipx = max(0, (int) u.ux - COx / 2); + clipxmax = clipx + COx; + if (clipxmax > COLNO) { + clipxmax = COLNO; + clipx = clipxmax - COx; + } + clipy = max(0, (int) u.uy - LIx / 2); + clipymax = clipy + LIx; + if (clipymax > ROWNO) { + clipymax = ROWNO; + clipy = clipymax - LIx; + } + clip_saved_level = u.uz; + } +#endif + if (cw->type == NHW_MENU || cw->type == NHW_TEXT) { RectFill(w->RPort, w->BorderLeft, w->BorderTop, w->Width - w->BorderRight - 1, @@ -1418,11 +1478,10 @@ register winid win; /* Dismiss the window from the screen */ void -dismiss_nhwindow(win) -register winid win; +dismiss_nhwindow(winid win) { - register struct Window *w; - register struct amii_WinDesc *cw; + struct Window *w; + struct amii_WinDesc *cw; if (win == WIN_ERR || (cw = amii_wins[win]) == NULL) { panic(winpanicstr, win, "dismiss_nhwindow"); @@ -1458,9 +1517,9 @@ register winid win; } void -amii_exit_nhwindows(str) -const char *str; +amii_exit_nhwindows(const char *str) { + /* Seems strange to have to do this... but we need the BASE window * left behind... */ @@ -1475,15 +1534,14 @@ const char *str; } void -amii_display_nhwindow(win, blocking) -winid win; -boolean blocking; +amii_display_nhwindow(winid win, boolean blocking) { menu_item *mip; int cnt; static int lastwin = -1; struct amii_WinDesc *cw; + if (!Initialized) return; lastwin = win; @@ -1513,13 +1571,12 @@ boolean blocking; } void -amii_curs(window, x, y) -winid window; -register int x, y; +amii_curs(winid window, int x, int y) { - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL) panic(winpanicstr, window, "curs"); @@ -1540,8 +1597,14 @@ register int x, y; cw->curx = x; cw->cury = y; + /* Silently skip rendering for out-of-bounds coordinates */ + if (cw->rows > 0 && y >= cw->rows) + return; + if (cw->cols > 0 && x >= cw->cols) + return; + #ifdef DEBUG - if (x < 0 || y < 0 || y >= cw->rows || x >= cw->cols) { + if (0 && (x < 0 || y < 0 || y >= cw->rows || x >= cw->cols)) { char *s = "[unknown type]"; switch (cw->type) { case NHW_MESSAGE: @@ -1663,12 +1726,10 @@ printf("pos: (%d,%d)->(%d,%d)\n",x,y,qqx,qqy); } void -amii_set_text_font(name, size) -char *name; -int size; +amii_set_text_font(char *name, int size) { - register int i; - register struct amii_WinDesc *cw; + int i; + struct amii_WinDesc *cw; int osize = TextsFont13.ta_YSize; static char nname[100]; @@ -1709,11 +1770,10 @@ int size; } void -kill_nhwindows(all) -register int all; +kill_nhwindows(int all) { - register int i; - register struct amii_WinDesc *cw; + int i; + struct amii_WinDesc *cw; /* Foreach open window in all of amii_wins[], CloseShWindow, free memory */ @@ -1726,12 +1786,10 @@ register int all; } void -amii_cl_end(cw, curs_pos) -register struct amii_WinDesc *cw; -register int curs_pos; +amii_cl_end(struct amii_WinDesc *cw, int curs_pos) { - register struct Window *w = cw->win; - register int oy, ox; + struct Window *w = cw->win; + int oy, ox; if (!w) panic("NULL window pointer in amii_cl_end()"); @@ -1745,12 +1803,11 @@ register int curs_pos; } void -cursor_off(window) -winid window; +cursor_off(winid window) { - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; int curx, cury; int x, y; long dmode; @@ -1805,13 +1862,12 @@ winid window; } void -cursor_on(window) -winid window; +cursor_on(winid window) { int x, y; - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; unsigned char ch; long dmode; short apen, bpen; @@ -1858,10 +1914,13 @@ winid window; if (WINVERS_AMIV && cw->type == NHW_MAP) { cursor_common(rp, x, y); } else { - Move(rp, x, y); - ch = CURSOR_CHAR; - Text(rp, &ch, 1); - Move(rp, x, y); + if (w && x >= 0 && y >= 0 + && x < w->Width && y < w->Height) { + Move(rp, x, y); + ch = CURSOR_CHAR; + Text(rp, &ch, 1); + Move(rp, x, y); + } } SetDrMd(rp, dmode); @@ -1870,9 +1929,7 @@ winid window; } static void -cursor_common(rp, x, y) -struct RastPort *rp; -int x, y; +cursor_common(struct RastPort *rp, int x, int y) { int x1, x2, y1, y2; @@ -1895,29 +1952,27 @@ int x, y; } void -amii_suspend_nhwindows(str) -const char *str; +amii_suspend_nhwindows(const char *str) { if (HackScreen) ScreenToBack(HackScreen); } void -amii_resume_nhwindows() +amii_resume_nhwindows(void) { if (HackScreen) ScreenToFront(HackScreen); } void -amii_bell() +amii_bell(void) { DisplayBeep(NULL); } void -removetopl(cnt) -int cnt; +removetopl(int cnt) { struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; /* NB - this is sufficient for @@ -1935,7 +1990,7 @@ int cnt; #ifdef PORT_HELP void -port_help() +port_help(void) { display_file(PORT_HELP, 1); } @@ -1951,17 +2006,20 @@ port_help() */ void -amii_print_glyph(win, x, y, glyph, bkglyph) -winid win; -coordxy x, y; -int glyph, bkglyph; +amii_print_glyph(winid win, coordxy x, coordxy y, + const glyph_info *glyphinfo, + const glyph_info *bkglyphinfo UNUSED) { struct amii_WinDesc *cw; uchar ch; + int glyph; int color, och; extern const int zapcolors[]; unsigned special; + + glyph = glyphinfo->glyph; + /* In order for the overview window to work, we can not clip here */ if (!WINVERS_AMIV) { #ifdef CLIPPING @@ -1993,14 +2051,8 @@ if(u.uz.dlevel != x){ } else /* AMII, or Rogue level in either version */ { /* map glyph to character and color */ -#if 0 - (void) mapglyph(glyph, &och, &color, &special, x, y, 0); - ch = (uchar) och; -#else - glyph_info gi; - map_glyphinfo(0, 0, glyph, 0, &gi); - ch = gi.ttychar; -#endif + ch = glyphinfo->ttychar; + color = glyphinfo->gm.sym.color; if (WINVERS_AMIV) { /* implies Rogue level here */ amii_curs(win, x, y); amiga_print_glyph(win, NO_COLOR, ch + 10000); @@ -2021,11 +2073,11 @@ if(u.uz.dlevel != x){ /* Make sure the user sees a text string when no windowing is available */ void -amii_raw_print(s) -register const char *s; +amii_raw_print(const char *s) { int argc = 0; + if (!s) return; if (amiIDisplay) @@ -2057,11 +2109,11 @@ register const char *s; */ void -amii_raw_print_bold(s) -register const char *s; +amii_raw_print_bold(const char *s) { int argc = 0; + if (!s) return; @@ -2092,9 +2144,10 @@ register const char *s; /* Rebuild/update the inventory if the window is up. */ void -amii_update_inventory() +amii_update_inventory(int arg UNUSED) { - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (WIN_INVEN != WIN_ERR && (cw = amii_wins[WIN_INVEN]) && cw->type == NHW_MENU && cw->win) { @@ -2102,10 +2155,17 @@ amii_update_inventory() } } +/* Stub for ctrl_nhwindow - no special handling needed for Amiga */ +win_request_info * +amii_ctrl_nhwindow(winid window UNUSED, int request UNUSED, win_request_info *wri UNUSED) +{ + return (win_request_info *) 0; +} + /* Humm, doesn't really do anything useful */ void -amii_mark_synch() +amii_mark_synch(void) { if (!amiIDisplay) fflush(stderr); @@ -2116,7 +2176,7 @@ amii_mark_synch() * ask for a key to be pressed. */ void -amii_wait_synch() +amii_wait_synch(void) { if (!amiIDisplay || amiIDisplay->rawprint) { if (amiIDisplay) @@ -2130,7 +2190,7 @@ amii_wait_synch() } void -amii_setclipped() +amii_setclipped(void) { #ifdef CLIPPING clipping = TRUE; @@ -2141,12 +2201,35 @@ amii_setclipped() #endif } +/* Redraw a rectangular region of the map via newsym(). Used after + ScrollRaster() shifts existing pixels — only the exposed strip needs + redrawing. Does NOT flush; the caller flushes after all regions. */ +static void +redraw_map_region(int x1, int y1, int x2, int y2) +{ + int x, y; + + if (!u.ux) + return; + if (x1 < 1) x1 = 1; + if (y1 < 0) y1 = 0; + if (x2 >= COLNO) x2 = COLNO - 1; + if (y2 >= ROWNO) y2 = ROWNO - 1; + for (y = y1; y <= y2; y++) + for (x = x1; x <= x2; x++) { + /* Invalidate the glyph buffer so newsym() redraws even if + * the glyph hasn't changed — the pixels were shifted by + * ScrollRaster and no longer match the buffer. */ + gg.gbuf[y][x].glyphinfo.glyph = NO_GLYPH; + newsym(x, y); + } +} + /* XXX still to do: suppress scrolling if we violate the boundary but the * edge of the map is already displayed */ void -amii_cliparound(x, y) -register int x, y; +amii_cliparound(int x, int y) { #ifdef CLIPPING int oldx = clipx, oldy = clipy; @@ -2155,8 +2238,9 @@ register int x, y; #define SCROLLCNT 1 /* Get there in 3 moves... */ int scrollcnt = SCROLLCNT; /* ...or 1 if we changed level */ - if (!clipping) /* And 1 in anycase, cleaner, simpler, quicker */ + if (!clipping) { /* And 1 in anycase, cleaner, simpler, quicker */ return; + } if (Is_rogue_level(&u.uz)) { struct Window *w = amii_wins[WIN_MAP]->win; @@ -2173,16 +2257,22 @@ register int x, y; * reasonablely large window extra motion is avoided; for * the rogue level hopefully this means no motion at all. */ - { - static d_level saved_level = { 127, 127 }; /* XXX */ - - if (!on_level(&u.uz, &saved_level)) { - scrollcnt = 1; /* jump with blanking */ - clipx = clipy = 0; - clipxmax = COx; - clipymax = LIx; - saved_level = u.uz; /* save as new current level */ + if (!on_level(&u.uz, &clip_saved_level)) { + scrollcnt = 1; /* jump with blanking */ + /* Center viewport on the player for the new level. */ + clipx = max(0, x - COx / 2); + clipxmax = clipx + COx; + if (clipxmax > COLNO) { + clipxmax = COLNO; + clipx = clipxmax - COx; } + clipy = max(0, y - LIx / 2); + clipymax = clipy + LIx; + if (clipymax > ROWNO) { + clipymax = ROWNO; + clipy = clipymax - LIx; + } + clip_saved_level = u.uz; /* save as new current level */ } if (x <= clipx + xclipbord) { @@ -2204,13 +2294,12 @@ register int x, y; reclip = 1; if (clipx != oldx || clipy != oldy || clipxmax != oldxmax || clipymax != oldymax) { -#ifndef NOSCROLLRASTER struct Window *w = amii_wins[WIN_MAP]->win; struct RastPort *rp = w->RPort; - int xdelta, ydelta, xmod, ymod, i; - int incx, incy, mincx, mincy; - int savex, savey, savexmax, saveymax; - int scrx, scry; + int dx = clipx - oldx; + int dy = clipy - oldy; + int scrx, scry; /* tile pixel dimensions */ + int halfW, halfH; /* half viewport in tiles */ if (Is_rogue_level(&u.uz)) { scrx = rp->TxWidth; @@ -2220,129 +2309,63 @@ register int x, y; scry = mysize; } - /* Ask that the glyph routines not draw the overview window */ - reclip = 2; - cursor_off(WIN_MAP); + halfW = COx / 2; + halfH = LIx / 2; - /* Compute how far we are moving in terms of tiles */ - mincx = clipx - oldx; - mincy = clipy - oldy; + /* Erase the map cursor before shifting pixels, otherwise the + old cursor position leaves a COMPLEMENT artifact on screen. */ + if (WIN_MAP != WIN_ERR) + cursor_off(WIN_MAP); - /* How many tiles to get there in SCROLLCNT moves */ - incx = (clipx - oldx) / scrollcnt; - incy = (clipy - oldy) / scrollcnt; - - /* If less than SCROLLCNT tiles, then move by 1 tile if moving at all - */ - if (incx == 0) - incx = (mincx != 0); - if (incy == 0) - incy = (mincy != 0); - - /* Get count of pixels to move each iteration and final pixel count */ - xdelta = ((clipx - oldx) * scrx) / scrollcnt; - xmod = ((clipx - oldx) * scrx) % scrollcnt; - ydelta = ((clipy - oldy) * scry) / scrollcnt; - ymod = ((clipy - oldy) * scry) % scrollcnt; - - /* Preserve the final move location */ - savex = clipx; - savey = clipy; - saveymax = clipymax; - savexmax = clipxmax; - -/* - * Set clipping rectangle to be just the region that will be exposed so - * that drawing will be faster - */ -#if 0 /* Doesn't seem to work quite the way it should */ - /* In some cases hero is 'centered' offscreen */ - if( xdelta < 0 ) - { - clipx = oldx; - clipxmax = clipx + incx; - } - else if( xdelta > 0 ) - { - clipxmax = oldxmax; - clipx = clipxmax - incx; - } - else - { - clipx = oldx; - clipxmax = oldxmax; - } - - if( ydelta < 0 ) - { - clipy = oldy; - clipymax = clipy + incy; - } - else if( ydelta > 0 ) - { - clipymax = oldymax; - clipy = clipymax - incy; - } - else - { - clipy = oldy; - clipymax = oldymax; - } -#endif - /* Now, in scrollcnt moves, move the picture toward the final view */ - for (i = 0; i < scrollcnt; ++i) { -#ifdef DISPMAP - if (i == scrollcnt - 1 && (xmod != 0 || ymod != 0) - && (xdelta != 0 || ydelta != 0)) { - incx += (clipx - oldx) % scrollcnt; - incy += (clipy - oldy) % scrollcnt; - xdelta += xmod; - ydelta += ymod; + /* Large jumps (teleport, level change): just redraw everything. */ + if (abs(dx) > halfW || abs(dy) > halfH + || scrollcnt != SCROLLCNT) { + { + int savedAPen = rp->FgPen; + int savedDrMd = rp->DrawMode; + SetAPen(rp, amii_otherBPen); + SetDrMd(rp, JAM1); + RectFill(rp, w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight - 1, + w->Height - w->BorderBottom - 1); + SetAPen(rp, savedAPen); + SetDrMd(rp, savedDrMd); } -#endif - /* Scroll the raster if we are scrolling */ - if (xdelta != 0 || ydelta != 0) { - ScrollRaster(rp, xdelta, ydelta, w->BorderLeft, w->BorderTop, - w->Width - w->BorderRight - 1, - w->Height - w->BorderBottom - 1); + redraw_map(FALSE); + } else { + /* Flush pending glyphs — they reference old clip coords */ + flush_glyph_buffer(w); - if (mincx == 0) - incx = 0; - else - mincx -= incx; + /* Hardware-blit the viewport by the scroll delta */ + ScrollRaster(rp, dx * scrx, dy * scry, + w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight - 1, + w->Height - w->BorderBottom - 1); - clipx += incx; - clipxmax += incx; + /* Redraw only the exposed strip(s) */ + if (dx > 0) + redraw_map_region(clipxmax - dx, clipy, + clipxmax, clipymax - 1); + else if (dx < 0) + redraw_map_region(clipx, clipy, + clipx - dx, clipymax - 1); - if (mincy == 0) - incy = 0; - else - mincy -= incy; + if (dy > 0) + redraw_map_region(clipx, clipymax - dy, + clipxmax, clipymax - 1); + else if (dy < 0) + redraw_map_region(clipx, clipy, + clipxmax, clipy - dy - 1); - clipy += incy; - clipymax += incy; - - /* Draw the exposed portion */ - redraw_map(); - flush_glyph_buffer(amii_wins[WIN_MAP]->win); - } + flush_glyph_buffer(w); } - - clipx = savex; - clipy = savey; - clipymax = saveymax; - clipxmax = savexmax; -#endif - redraw_map(); - flush_glyph_buffer(amii_wins[WIN_MAP]->win); } reclip = 0; #endif } void -flushIDCMP(port) -struct MsgPort *port; +flushIDCMP(struct MsgPort *port) { struct Message *msg; while (msg = GetMsg(port)) diff --git a/outdated/sys/amiga/winkey.c b/sys/amiga/winkey.c similarity index 89% rename from outdated/sys/amiga/winkey.c rename to sys/amiga/winkey.c index 9534c0c6d..f2686bfde 100644 --- a/outdated/sys/amiga/winkey.c +++ b/sys/amiga/winkey.c @@ -12,12 +12,14 @@ #include "winproto.h" #endif -amii_nh_poskey(x, y, mod) int *x, *y, *mod; +int +amii_nh_poskey(coordxy *x, coordxy *y, int *mod) { struct amii_WinDesc *cw; WETYPE type; struct RastPort *rp; struct Window *w; + /* No entry log for nh_poskey -- too noisy (called constantly) */ if (cw = amii_wins[WIN_MESSAGE]) { cw->wflags &= ~FLMAP_SKIP; @@ -59,10 +61,11 @@ amii_nh_poskey(x, y, mod) int *x, *y, *mod; } int -amii_nhgetch() +amii_nhgetch(void) { int ch; struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; + /* No entry log for nhgetch -- too noisy (called constantly) */ if (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP]) { cursor_on(WIN_MAP); @@ -75,15 +78,15 @@ amii_nhgetch() } void -amii_get_nh_event() +amii_get_nh_event(void) { /* nothing now - later I have no idea. Is this just a Mac hook? */ } void -amii_getret() +amii_getret(void) { - register int c; + int c; raw_print(""); raw_print("Press Return..."); diff --git a/outdated/sys/amiga/winproto.h b/sys/amiga/winproto.h similarity index 88% rename from outdated/sys/amiga/winproto.h rename to sys/amiga/winproto.h index efa1e9b58..d855e50fe 100644 --- a/outdated/sys/amiga/winproto.h +++ b/sys/amiga/winproto.h @@ -8,10 +8,9 @@ void EditClipping(void); void DrawCol(struct Window *w, int idx, UWORD *colors); void DispCol(struct Window *w, int idx, UWORD *colors); void amii_change_color(int, long, int); -char *amii_get_color_string(); +char *amii_get_color_string(void); void amii_getlin(const char *prompt, char *bufp); void getlind(const char *prompt, char *bufp, const char *dflt); -char *amii_get_color_string(void); int filecopy(char *from, char *to); char *basename(char *str); char *dirname(char *str); @@ -33,15 +32,15 @@ void amii_scrollmsg(register struct Window *w, register struct amii_WinDesc *cw); /* winkey.c */ -int amii_nh_poskey(int *x, int *y, int *mod); +int amii_nh_poskey(coordxy *x, coordxy *y, int *mod); int amii_nhgetch(void); void amii_get_nh_event(void); void amii_getret(void); /* winmenu.c */ void amii_start_menu(winid window, unsigned long); -void amii_add_menu(winid, int, const anything *, CHAR_P, CHAR_P, int, - const char *, unsigned int); +void amii_add_menu(winid, const glyph_info *, const anything *, CHAR_P, CHAR_P, + int, int, const char *, unsigned int); void amii_end_menu(winid, const char *); int amii_select_menu(winid, int, menu_item **); int DoMenuScroll(int win, int blocking, int how, menu_item **); @@ -55,7 +54,6 @@ struct Window *OpenShWindow(struct NewWindow *nw); void CloseShWindow(struct Window *win); int ConvertKey(struct IntuiMessage *message); int kbhit(void); -int kbhit(void); int amikbhit(void); int WindowGetchar(void); WETYPE WindowGetevent(void); @@ -101,19 +99,19 @@ void amii_resume_nhwindows(void); void amii_bell(void); void removetopl(int cnt); void port_help(void); -void amii_print_glyph(winid win, coordxy x, coordxy y, int glyph, int bkglyph); +void amii_print_glyph(winid win, coordxy x, coordxy y, const glyph_info *glyphinfo, const glyph_info *bkglyphinfo); void amii_raw_print(const char *s); void amii_raw_print_bold(const char *s); -void amii_update_inventory(void); +void amii_update_inventory(int); void amii_mark_synch(void); void amii_wait_synch(void); void amii_setclipped(void); void amii_cliparound(int x, int y); void amii_set_text_font(char *font, int size); -BitMapHeader ReadImageFiles(char **, struct BitMap **, char **); +BitMapHeader ReadImageFile(const char *, struct BitMap **); +void FreeImageFile(struct BitMap **); BitMapHeader ReadTileImageFiles(void); -void FreeImageFiles(char **, struct BitMap **); -void FreeTileImageFiles(); +void FreeTileImageFiles(void); /* winami.c */ #ifdef SHAREDLIB @@ -124,12 +122,10 @@ void amii_askname(void); void amii_player_selection(void); void RandomWindow(char *name); int amii_get_ext_cmd(void); -char amii_yn_function(const char *prompt, const char *resp, char def); char amii_yn_function(const char *query, const char *resp, char def); void amii_display_file(const char *fn, boolean complain); void SetBorder(struct Gadget *gd); -void *malloc(register unsigned size); -void free(void *q); +/* malloc/free provided by stdlib.h */ #ifdef SHAREDLIB /* amilib.c */ @@ -141,6 +137,8 @@ void setup_librefs(WinamiBASE *base); void Abort(long rc); #endif +win_request_info *amii_ctrl_nhwindow(winid, int, win_request_info *); + /* amirip.c */ void amii_outrip(winid tmpwin, int how, time_t when); @@ -151,4 +149,3 @@ int GlyphToIcon(int glyph); void dispmap_sanity(void); int dispmap_sanity1(int); #endif -void FreeTileImageFiles(void); diff --git a/outdated/sys/amiga/winreq.c b/sys/amiga/winreq.c similarity index 95% rename from outdated/sys/amiga/winreq.c rename to sys/amiga/winreq.c index af4c303de..910adeb86 100644 --- a/outdated/sys/amiga/winreq.c +++ b/sys/amiga/winreq.c @@ -67,16 +67,16 @@ struct NewWindow StrWindow = { void ClearCol(struct Window *w); void -EditColor() +EditColor(void) { - extern char configfile[]; + const char *configfile = get_configfile(); int i, done = 0, okay = 0; long code, qual, class; - register struct Gadget *gd, *dgad; - register struct Window *nw; - register struct IntuiMessage *imsg; - register struct PropInfo *pip; - register struct Screen *scrn; + struct Gadget *gd, *dgad; + struct Window *nw; + struct IntuiMessage *imsg; + struct PropInfo *pip; + struct Screen *scrn; long aidx; int msx, msy; int curcol = 0, drag = 0; @@ -128,11 +128,7 @@ EditColor() #ifdef INTUI_NEW_LOOK Col_NewWindowStructure1.Extension = wintags; Col_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) -2; fillhook.h_SubEntry = 0; #endif @@ -248,7 +244,7 @@ EditColor() for (i = 0; i < amii_numcolors; ++i) { fprintf(nfp, "%03x", colors[i]); if ((i + 1) < amii_numcolors) - putc(',', nfp); + putc('/', nfp); } putc('\n', nfp); } @@ -356,11 +352,11 @@ EditClipping(void) char buf[40]; int done = 0, okay = 0; long code, qual, class; - register struct Gadget *gd, *dgad; - register struct Window *nw; - register struct IntuiMessage *imsg; - register struct PropInfo *pip; - register struct Screen *scrn; + struct Gadget *gd, *dgad; + struct Window *nw; + struct IntuiMessage *imsg; + struct PropInfo *pip; + struct Screen *scrn; long aidx; int lmxsize = mxsize, lmysize = mysize; int lxclipbord = xclipbord, lyclipbord = yclipbord; @@ -388,11 +384,7 @@ EditClipping(void) #ifdef INTUI_NEW_LOOK ClipNewWindowStructure1.Extension = wintags; ClipNewWindowStructure1.Flags |= WFLG_NW_EXTENDED; -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) -2; fillhook.h_SubEntry = 0; #endif @@ -546,8 +538,7 @@ EditClipping(void) } char * -dirname(str) -char *str; +dirname(char *str) { char *t, c; static char dir[300]; @@ -555,9 +546,9 @@ char *str; t = strrchr(str, '/'); if (!t) t = strrchr(str, ':'); - if (!t) - t = str; - else { + if (!t) { + dir[0] = '\0'; + } else { c = *t; *t = 0; strcpy(dir, str); @@ -567,8 +558,7 @@ char *str; } char * -basename(str) -char *str; +basename(char *str) { char *t; @@ -582,7 +572,8 @@ char *str; return (t); } -filecopy(from, to) char *from, *to; +int +filecopy(char *from, char *to) { char *buf; int i = 0; @@ -606,7 +597,7 @@ filecopy(from, to) char *from, *to; } /* The colornames, and the default values for the pens */ -static struct COLDEF { +struct COLDEF { char *name, *defval; }; struct COLDEF amii_colnames[AMII_MAXCOLORS] = { @@ -657,10 +648,7 @@ ClearCol(struct Window *w) } void -DrawCol(w, idx, colors) -struct Window *w; -int idx; -UWORD *colors; +DrawCol(struct Window *w, int idx, UWORD *colors) { int bxorx, bxory, bxxlen, bxylen; int i, incx, incy, r, g, b; @@ -742,10 +730,7 @@ UWORD *colors; } void -DispCol(w, idx, colors) -struct Window *w; -int idx; -UWORD *colors; +DispCol(struct Window *w, int idx, UWORD *colors) { char buf[50]; char *colname, *defval; @@ -824,26 +809,21 @@ amii_setpens(int count) /* Generate a requester for a string value. */ void -amii_getlin(prompt, bufp) -const char *prompt; -char *bufp; +amii_getlin(const char *prompt, char *bufp) { getlind(prompt, bufp, 0); } /* and with default */ void -getlind(prompt, bufp, dflt) -const char *prompt; -char *bufp; -const char *dflt; +getlind(const char *prompt, char *bufp, const char *dflt) { #ifndef TOPL_GETLINE - register struct Window *cwin; - register struct IntuiMessage *imsg; - register long class, code, qual; - register int aredone = 0; - register struct Gadget *gd; + struct Window *cwin; + struct IntuiMessage *imsg; + long class, code, qual; + int aredone = 0; + struct Gadget *gd; static int once; *StrString = 0; @@ -872,11 +852,7 @@ const char *dflt; #ifdef INTUI_NEW_LOOK StrWindow.Extension = wintags; StrWindow.Flags |= WFLG_NW_EXTENDED; -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) -2; fillhook.h_SubEntry = 0; #endif @@ -1006,9 +982,7 @@ const char *dflt; } void -amii_change_color(pen, val, rev) -int pen, rev; -long val; +amii_change_color(int pen, long val, int rev) { if (rev) sysflags.amii_curmap[pen] = ~val; @@ -1020,12 +994,13 @@ long val; } char * -amii_get_color_string() +amii_get_color_string(void) { int i; char s[10]; static char buf[BUFSZ]; + *buf = 0; for (i = 0; i < min(32, amii_numcolors); ++i) { sprintf(s, "%s%03lx", i ? "/" : "", (long) sysflags.amii_curmap[i]); diff --git a/outdated/sys/amiga/winstr.c b/sys/amiga/winstr.c similarity index 95% rename from outdated/sys/amiga/winstr.c rename to sys/amiga/winstr.c index ea7d65343..a3801fff1 100644 --- a/outdated/sys/amiga/winstr.c +++ b/sys/amiga/winstr.c @@ -14,10 +14,7 @@ /* Put a string into the indicated window using the indicated attribute */ void -amii_putstr(window, attr, str) -winid window; -int attr; -const char *str; +amii_putstr(winid window, int attr, const char *str) { int fudge; int len; @@ -27,6 +24,7 @@ const char *str; int i, j, n0, bottom, totalvis, wheight; static int wrapping = 0; + /* Always try to avoid a panic when there is no window */ if (window == WIN_ERR) { window = WIN_BASE; @@ -101,13 +99,13 @@ const char *str; memcpy(cw->data, &cw->data[1], (iflags.msg_history - 1) * sizeof(char *)); cw->data[iflags.msg_history - 1] = - (char *) alloc(strlen(gt.toplines) + 5); + (char *) alloc(strlen(gt.toplines) + SOFF + 4); strcpy(cw->data[i = iflags.msg_history - 1] + SOFF + (scrollmsg != 0), gt.toplines); } else { /* Otherwise, allocate a new one and copy the line in */ - cw->data[cw->maxrow] = (char *) alloc(strlen(gt.toplines) + 5); + cw->data[cw->maxrow] = (char *) alloc(strlen(gt.toplines) + SOFF + 4); strcpy(cw->data[i = cw->maxrow++] + SOFF + (scrollmsg != 0), gt.toplines); } @@ -196,7 +194,10 @@ const char *str; /* Display when beam at top to avoid flicker... */ WaitTOF(); - Text(w->RPort, (char *) str, strlen((char *) str)); + { int slen = strlen((char *) str); + if (slen > cw->cols) slen = cw->cols; + Text(w->RPort, (char *) str, slen); + } if (cw->cols > strlen(str)) TextSpaces(w->RPort, cw->cols - strlen(str)); @@ -286,9 +287,7 @@ const char *str; } void -amii_scrollmsg(w, cw) -register struct Window *w; -register struct amii_WinDesc *cw; +amii_scrollmsg(struct Window *w, struct amii_WinDesc *cw) { int bottom, wheight; @@ -311,8 +310,7 @@ register struct amii_WinDesc *cw; } int -amii_msgborder(w) -struct Window *w; +amii_msgborder(struct Window *w) { register int bottom; @@ -325,8 +323,7 @@ struct Window *w; } void -outmore(cw) -register struct amii_WinDesc *cw; +outmore(struct amii_WinDesc *cw) { struct Window *w = cw->win; @@ -359,11 +356,7 @@ register struct amii_WinDesc *cw; } void -outsubstr(cw, str, len, fudge) -register struct amii_WinDesc *cw; -char *str; -int len; -int fudge; +outsubstr(struct amii_WinDesc *cw, char *str, int len, int fudge) { struct Window *w = cw->win; @@ -387,10 +380,7 @@ int fudge; /* Put a graphics character onto the screen */ void -amii_putsym(st, i, y, c) -winid st; -int i, y; -CHAR_P c; +amii_putsym(winid st, int i, int y, CHAR_P c) { amii_curs(st, i, y); Text(amii_wins[st]->win->RPort, &c, 1); @@ -399,8 +389,7 @@ CHAR_P c; /* Add to the last line in the message window */ void -amii_addtopl(s) -const char *s; +amii_addtopl(const char *s) { register struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; @@ -413,9 +402,7 @@ const char *s; } void -TextSpaces(rp, nr) -struct RastPort *rp; -int nr; +TextSpaces(struct RastPort *rp, int nr) { if (nr < 1) return; @@ -429,7 +416,7 @@ int nr; } void -amii_remember_topl() +amii_remember_topl(void) { /* ignore for now. I think this will be done automatically by * the code writing to the message window, but I could be wrong. @@ -437,12 +424,13 @@ amii_remember_topl() } int -amii_doprev_message() +amii_doprev_message(void) { struct amii_WinDesc *cw; struct Window *w; char *str; + if (WIN_MESSAGE == WIN_ERR || (cw = amii_wins[WIN_MESSAGE]) == NULL || (w = cw->win) == NULL) { panic(winpanicstr, WIN_MESSAGE, "doprev_message"); diff --git a/sys/amiga/xpm2iff_host.c b/sys/amiga/xpm2iff_host.c new file mode 100644 index 000000000..589d4f56f --- /dev/null +++ b/sys/amiga/xpm2iff_host.c @@ -0,0 +1,346 @@ +/* xpm2iff_host.c - host-side .xpm -> Amiga BMAP IFF converter. + * Copyright (c) 2026 by Ingo Paschke. + * NetHack may be freely redistributed. See license for details. + * + * Adapted from sys/amiga/xpm2iff.c, Copyright (c) 1995 by Gregg Wonderly. + * Rewritten for host-side cross-compilation using POSIX file I/O with + * explicit big-endian output instead of AmigaOS IFFParse library calls. + * + * Input: an XPM2 file, 1 char per pixel. + * Output: a BMAP IFF file readable by sys/amiga/winchar.c (tomb.iff). + */ + +#include +#include +#include +#include +#include + +/* ------------------------------------------------------------------ + * XPM screen descriptor and color translation table + * ------------------------------------------------------------------ */ + +static struct { + int Width; + int Height; + int Colors; + int BytesPerRow; +} XpmScreen; + +/* Translation table: indexed by the single XPM character code. + * slot = output palette index (0-based) + * flag = 1 if this entry is valid + * r,g,b = RGB components (0-255) */ +static struct { + unsigned char flag; + unsigned char r, g, b; + int slot; +} ttable[256]; + +/* ------------------------------------------------------------------ + * XPM parsing + * Adapted directly from sys/amiga/xpm2iff.c (already POSIX). + * ------------------------------------------------------------------ */ + +static FILE *xpmfh; + +#define XBUFSZ 2048 +static char xbuf[XBUFSZ]; + +/* Read the next quoted line from the XPM file. + * Returns a pointer to the content between the first pair of double-quotes, + * or NULL on EOF. Trailing ", and whitespace are stripped. */ +static char * +xpmgetline(void) +{ + char *bp; + do { + if (fgets(xbuf, XBUFSZ, xpmfh) == NULL) + return NULL; + } while (xbuf[0] != '"'); + + /* strip trailing <",> and whitespace */ + for (bp = xbuf; *bp; bp++) + ; + bp--; + while (isspace((unsigned char)*bp)) + bp--; + if (*bp == ',') + bp--; + if (*bp == '"') + bp--; + bp++; + *bp = '\0'; + + return &xbuf[1]; +} + +/* Open an XPM file and parse its header + color table. + * Populates XpmScreen and ttable[]. + * Returns 1 on success, 0 on failure. */ +static int +fopen_xpm_file(const char *fn) +{ + int temp; + char *xb; + + xpmfh = fopen(fn, "r"); + if (!xpmfh) + return 0; + + /* read dimensions header: "W H Colors 1" */ + xb = xpmgetline(); + if (!xb) + return 0; + if (sscanf(xb, "%d %d %d %d", + &XpmScreen.Width, &XpmScreen.Height, + &XpmScreen.Colors, &temp) != 4) + return 0; + if (temp != 1) { + fprintf(stderr, "xpm2iff_host: only 1 char/pixel XPM files supported\n"); + return 0; + } + + /* read color map: "%c c #rrggbb" */ + { + int ccount = 0; + while (ccount < XpmScreen.Colors) { + char idx; + int r, g, b; + xb = xpmgetline(); + if (!xb) + return 0; + if (sscanf(xb, "%c c #%2x%2x%2x", &idx, &r, &g, &b) != 4) { + fprintf(stderr, "xpm2iff_host: bad color entry: %s\n", xb); + return 0; + } + ttable[(unsigned char)idx].flag = 1; + ttable[(unsigned char)idx].r = (unsigned char)r; + ttable[(unsigned char)idx].g = (unsigned char)g; + ttable[(unsigned char)idx].b = (unsigned char)b; + ttable[(unsigned char)idx].slot = ccount; + ccount++; + } + } + return 1; +} + +/* ------------------------------------------------------------------ + * Bitplane packing + * ------------------------------------------------------------------ */ + +static char **planes; + +#define SETBIT(plane, plane_offset, col, value) \ + do { \ + if (value) \ + planes[plane][plane_offset + ((col) / 8)] \ + |= (char)(1 << (7 - ((col) & 7))); \ + } while (0) + +static void +conv_image(int nplanes) +{ + int row, col, planeno; + + for (row = 0; row < XpmScreen.Height; row++) { + char *xb = xpmgetline(); + int plane_offset; + if (!xb) + return; + plane_offset = row * XpmScreen.BytesPerRow; + for (col = 0; col < XpmScreen.Width; col++) { + int color = (unsigned char)xb[col]; + int slot; + if (!ttable[color].flag) { + fprintf(stderr, "xpm2iff_host: bad image data at row %d col %d\n", + row, col); + continue; + } + slot = ttable[color].slot; + for (planeno = 0; planeno < nplanes; planeno++) + SETBIT(planeno, plane_offset, col, slot & (1 << planeno)); + } + } +} + +/* ------------------------------------------------------------------ + * Big-endian IFF output helpers + * ------------------------------------------------------------------ */ + +static FILE *iff_out; + +static void +wr32(uint32_t v) +{ + fputc((v >> 24) & 0xff, iff_out); + fputc((v >> 16) & 0xff, iff_out); + fputc((v >> 8) & 0xff, iff_out); + fputc( v & 0xff, iff_out); +} + +static void +write_chunk(const char *id, const void *data, uint32_t size) +{ + fwrite(id, 1, 4, iff_out); + wr32(size); + fwrite(data, 1, size, iff_out); + if (size & 1) + fputc(0, iff_out); +} + +/* ------------------------------------------------------------------ + * main + * ------------------------------------------------------------------ */ + +int +main(int argc, char **argv) +{ + int i, nplanes, colors; + uint32_t pbytes, plne_size, form_size; + + if (argc != 3) { + fprintf(stderr, "Usage: %s source.xpm destination.iff\n", argv[0]); + return 1; + } + + if (!fopen_xpm_file(argv[1])) { + fprintf(stderr, "%s: failed to open or parse XPM file\n", argv[1]); + return 1; + } + + /* nplanes = ceil(log2(Colors)) */ + nplanes = 0; + i = XpmScreen.Colors - 1; + while (i > 0) { nplanes++; i >>= 1; } + + colors = 1 << nplanes; + + XpmScreen.BytesPerRow = ((XpmScreen.Width + 15) / 16) * 2; + pbytes = (uint32_t)XpmScreen.BytesPerRow * (uint32_t)XpmScreen.Height; + + /* Allocate zero-initialised bitplane buffers */ + planes = malloc(nplanes * sizeof(char *)); + if (!planes) { perror("malloc"); return 1; } + for (i = 0; i < nplanes; ++i) { + planes[i] = calloc(1, pbytes); + if (!planes[i]) { perror("calloc"); return 1; } + } + + /* Pack pixel data into bitplanes */ + conv_image(nplanes); + fclose(xpmfh); + + /* Open output IFF file */ + iff_out = fopen(argv[2], "wb"); + if (!iff_out) { perror(argv[2]); return 1; } + + /* Pre-compute FORM size: + * 4 (BMAP type tag) + * 8 + 20 (BMHD) + * 8 + 4 (CAMG) + * 8 + colors*3 (CMAP; colors is a power of 2, so colors*3 is even) + * 8 + 28 (PDAT: 7 x uint32_t) + * 8 + nplanes*pbytes (PLNE; pbytes is always even) + */ + plne_size = (uint32_t)nplanes * pbytes; + form_size = 4 + + (8 + 20) + + (8 + 4) + + (8 + (uint32_t)colors * 3) + + (8 + 28) + + (8 + plne_size); + + /* FORM header */ + fwrite("FORM", 1, 4, iff_out); + wr32(form_size); + fwrite("BMAP", 1, 4, iff_out); + + /* BMHD chunk */ + { + uint8_t bmhd[20]; + uint8_t *p = bmhd; + uint16_t w = (uint16_t)XpmScreen.Width; + uint16_t h = (uint16_t)XpmScreen.Height; + + p[0] = w >> 8; p[1] = w & 0xff; p += 2; /* w */ + p[0] = h >> 8; p[1] = h & 0xff; p += 2; /* h */ + memset(p, 0, 4); p += 4; /* x=0, y=0 */ + *p++ = (uint8_t)nplanes; /* nPlanes */ + *p++ = 0; /* masking: none */ + *p++ = 0; /* compression: none */ + *p++ = 0; /* reserved1 */ + p[0] = 0; p[1] = 0; p += 2; /* transparentColor */ + *p++ = 100; /* xAspect */ + *p++ = 100; /* yAspect */ + p[0] = 0; p[1] = 0; p += 2; /* pageWidth (not used) */ + p[0] = 0; p[1] = 0; p += 2; /* pageHeight (not used) */ + + write_chunk("BMHD", bmhd, 20); + } + + /* CAMG chunk: HIRES | LACE = 0x00008004 */ + { + uint8_t camg[4] = { 0x00, 0x00, 0x80, 0x04 }; + write_chunk("CAMG", camg, 4); + } + + /* CMAP chunk: built from ttable (no color reordering for XPM images) */ + { + uint8_t *cmap = calloc(colors, 3); + if (!cmap) { perror("calloc"); return 1; } + for (i = 0; i < 256; i++) { + if (ttable[i].flag) { + int s = ttable[i].slot; + cmap[s * 3 + 0] = ttable[i].r; + cmap[s * 3 + 1] = ttable[i].g; + cmap[s * 3 + 2] = ttable[i].b; + } + } + write_chunk("CMAP", cmap, (uint32_t)colors * 3); + free(cmap); + } + + /* PDAT chunk: 7 x uint32_t big-endian + * nplanes, pbytes, across=0, down=0, npics=1, xsize=Width, ysize=Height */ + { + uint32_t vals[7]; + uint8_t pdat[28]; + uint8_t *p = pdat; + + vals[0] = (uint32_t)nplanes; + vals[1] = pbytes; + vals[2] = 0; /* across: not a tile sheet */ + vals[3] = 0; /* down */ + vals[4] = 1; /* npics */ + vals[5] = (uint32_t)XpmScreen.Width; + vals[6] = (uint32_t)XpmScreen.Height; + + for (i = 0; i < 7; i++) { + p[0] = (vals[i] >> 24) & 0xff; + p[1] = (vals[i] >> 16) & 0xff; + p[2] = (vals[i] >> 8) & 0xff; + p[3] = vals[i] & 0xff; + p += 4; + } + write_chunk("PDAT", pdat, 28); + } + + /* PLNE chunk: concatenated bitplane data */ + fwrite("PLNE", 1, 4, iff_out); + wr32(plne_size); + for (i = 0; i < nplanes; ++i) + fwrite(planes[i], 1, pbytes, iff_out); + if (plne_size & 1) + fputc(0, iff_out); + + fclose(iff_out); + + for (i = 0; i < nplanes; ++i) free(planes[i]); + free(planes); + + printf("tomb.iff: %dx%d, %d colors (%d planes), %u bytes/plane\n", + XpmScreen.Width, XpmScreen.Height, colors, nplanes, + (unsigned)pbytes); + return 0; +} diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index 8850e2d82..fdfc599c6 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -128,6 +128,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ choose_windows(DEFAULT_WINDOW_SYS); + #if !defined(AMIGA) && !defined(GNUDOS) /* Save current directory and make sure it gets restored when * the game is exited. @@ -147,6 +148,10 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ if (dir == (char *) 0) dir = exepath(argv[0]); #endif +#if defined(AMIGA) && defined(HACKDIR) + if (dir == (char *) 0) + dir = HACKDIR; +#endif #ifdef _MSC_VER if (IsDebuggerPresent()) { static char exepath[_MAX_PATH]; diff --git a/sys/unix/hints/include/cross-post.370 b/sys/unix/hints/include/cross-post.370 index 01a998572..f28ec0fe1 100644 --- a/sys/unix/hints/include/cross-post.370 +++ b/sys/unix/hints/include/cross-post.370 @@ -229,6 +229,113 @@ mipspkg: dodata $(GAMEBIN) $(TARGETPFX)recover @echo MIPS package zip file $(TARGETPFX)nh370mips.zip endif # CROSS_TO_MIPS + +ifdef CROSS_TO_AMIGA +$(TARGETPFX)amidos.o : ../sys/amiga/amidos.c $(HACK_H) +$(TARGETPFX)amigst.o : ../sys/amiga/amigst.c $(HACK_H) +$(TARGETPFX)amirip.o : ../sys/amiga/amirip.c $(HACK_H) +$(TARGETPFX)amistack.o : ../sys/amiga/amistack.c $(HACK_H) +$(TARGETPFX)amitty.o : ../sys/amiga/amitty.c $(HACK_H) +$(TARGETPFX)amiwind.o : ../sys/amiga/amiwind.c \ + ../sys/amiga/amimenu.c $(HACK_H) +$(TARGETPFX)winami.o : ../sys/amiga/winami.c $(HACK_H) +$(TARGETPFX)winchar.o : ../sys/amiga/winchar.c tile.c $(HACK_H) +$(TARGETPFX)winfuncs.o : ../sys/amiga/winfuncs.c $(HACK_H) +$(TARGETPFX)winkey.o : ../sys/amiga/winkey.c $(HACK_H) +$(TARGETPFX)winamenu.o : ../sys/amiga/winamenu.c $(HACK_H) +$(TARGETPFX)winreq.o : ../sys/amiga/winreq.c \ + ../sys/amiga/colorwin.c \ + ../sys/amiga/clipwin.c $(HACK_H) +$(TARGETPFX)winstr.o : ../sys/amiga/winstr.c $(HACK_H) +$(GAMEBIN) : $(HOBJ) $(LUACROSSLIB) + $(TARGET_LINK) $(TARGET_LFLAGS) -o $(GAMEBIN) \ + $(HOBJ) $(WINLIB) $(TARGET_LIBS) +# +# Host-side IFF tile conversion tools (run on Linux, produce Amiga IFF files) +# +AMISRC = ../sys/amiga + +$(TARGETPFX)xpm2iff_host: $(AMISRC)/xpm2iff_host.c + $(CC) $(CFLAGS) -o $@ $< +$(TARGETPFX)tomb.iff: $(AMISRC)/grave16.xpm $(TARGETPFX)xpm2iff_host + $(TARGETPFX)xpm2iff_host $(AMISRC)/grave16.xpm $@ + +$(TARGETPFX)bmp2iff_host: $(AMISRC)/bmp2iff_host.c + $(CC) $(CFLAGS) -o $@ $< +$(TARGETPFX)tiles16.iff: ../dat/nhtiles.bmp $(TARGETPFX)bmp2iff_host + $(TARGETPFX)bmp2iff_host -planes 4 ../dat/nhtiles.bmp $@ +$(TARGETPFX)tiles32.iff: ../dat/nhtiles.bmp $(TARGETPFX)bmp2iff_host + $(TARGETPFX)bmp2iff_host -planes 5 ../dat/nhtiles.bmp $@ + +AMITILES = $(TARGETPFX)tiles16.iff $(TARGETPFX)tiles32.iff $(TARGETPFX)tomb.iff + +AMIREGEX_URL = https://github.com/garyhouston/regex.git +AMIREGEX_SRCDIR = $(AMISRC)/regex + +.PHONY: fetch-regex amigapkg amitiles + +fetch-regex: + @DSTDIR=sys/amiga/regex; \ + if [ ! -d src ]; then DSTDIR=../$$DSTDIR; fi; \ + if [ -f $$DSTDIR/regcomp.c ]; then \ + echo "BSD regex already present"; \ + else \ + echo "Fetching BSD regex from $(AMIREGEX_URL)"; \ + tmpdir=$$(mktemp -d) && \ + git clone --depth 1 $(AMIREGEX_URL) $$tmpdir && \ + cd $$tmpdir && \ + sh ./mkh -p regcomp.c > regcomp.ih && \ + sh ./mkh -p engine.c > engine.ih && \ + sh ./mkh -p regexec.c > regexec.ih && \ + sh ./mkh -p regerror.c > regerror.ih && \ + sh ./mkh -i _REGEX_H_ regex2.h regcomp.c \ + regexec.c regerror.c regfree.c > regex.h && \ + cd - > /dev/null && \ + mkdir -p $$DSTDIR && \ + for f in regcomp.c regexec.c regerror.c regfree.c \ + engine.c regex.h regex2.h cclass.h cname.h \ + utils.h regcomp.ih engine.ih regexec.ih \ + regerror.ih \ + COPYRIGHT; do \ + cp $$tmpdir/$$f $$DSTDIR/; \ + done && \ + rm -rf $$tmpdir && \ + echo "BSD regex installed in $$DSTDIR"; \ + fi +amitiles: $(AMITILES) + +UUDECODE = ../util/uudecode + +../util/uudecode: ../sys/share/uudecode.c + $(CC) $(CFLAGS) -o $@ $< + +amigapkg: $(AMITILES) ../util/uudecode + mkdir -p $(TARGETPFX)pkg/tiles $(TARGETPFX)pkg/hack + cp $(GAMEBIN) $(TARGETPFX)pkg/nethack + cp ../dat/nhdat $(TARGETPFX)pkg/nhdat + cp ../dat/license $(TARGETPFX)pkg/license + cp ../dat/symbols $(TARGETPFX)pkg/symbols + cp $(TARGETPFX)tiles16.iff $(TARGETPFX)pkg/tiles/tiles16.iff + cp $(TARGETPFX)tiles32.iff $(TARGETPFX)pkg/tiles/tiles32.iff + cp $(TARGETPFX)tomb.iff $(TARGETPFX)pkg/tomb.iff + cp ../sys/msdos/sysconf $(TARGETPFX)pkg/sysconf + cp ../doc/nethack.txt $(TARGETPFX)pkg/nethack.txt + ( cd $(TARGETPFX)pkg && ../../../util/uudecode ../../../sys/amiga/amifont8.uu && mv 8 hack/8 ) + ( cd $(TARGETPFX)pkg && ../../../util/uudecode ../../../sys/amiga/amifont.uu ) + cp $(AMISRC)/nethack.cnf $(TARGETPFX)pkg/nethack.cnf + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/dflticon.uu && \ + ../../../util/uudecode ../../../sys/amiga/dflticon.uu ) + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/NHinfo.uu && \ + ../../../util/uudecode ../../../sys/amiga/NHinfo.uu ) + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/NewGame.uu && \ + ../../../util/uudecode ../../../sys/amiga/NewGame.uu ) + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/HackWB.uu && \ + ../../../util/uudecode ../../../sys/amiga/HackWB.uu ) + touch $(TARGETPFX)pkg/record + ( cd $(TARGETPFX)pkg && zip -9r ../NH370AMI.ZIP * ) + @echo amiga package zip file $(TARGETPFX)NH370AMI.ZIP +endif # CROSS_TO_AMIGA + ifdef CROSS_SHARED # shared file dependencies $(TARGETPFX)pcmain.o : ../sys/share/pcmain.c $(HACK_H) diff --git a/sys/unix/hints/include/cross-pre1.370 b/sys/unix/hints/include/cross-pre1.370 index 203c06048..867886d9b 100644 --- a/sys/unix/hints/include/cross-pre1.370 +++ b/sys/unix/hints/include/cross-pre1.370 @@ -38,6 +38,16 @@ override TARGETPFX = $(TARGETDIR)/ override TARGET_LIBS= endif +ifdef CROSS_TO_AMIGA +CROSS=1 +BUILD_TARGET_LUA=1 +CROSS_SHARED=1 +override TARGET = amiga +override TARGETDIR=../targets/$(TARGET) +override TARGETPFX = $(TARGETDIR)/ +override TARGET_LIBS= +endif + ifdef CROSS override PREGAME= override BUILDMORE= diff --git a/sys/unix/hints/include/cross-pre2.370 b/sys/unix/hints/include/cross-pre2.370 index d0cdf513a..9e873e978 100644 --- a/sys/unix/hints/include/cross-pre2.370 +++ b/sys/unix/hints/include/cross-pre2.370 @@ -460,6 +460,97 @@ NCURSES_PLATFORM=MIPS endif # CROSS_TO_MIPS #================================================================= +#================================================================= + +ifdef CROSS_TO_AMIGA +#===============-================================================= +# AmigaOS m68k cross-compile recipe +#===============-================================================= +# Uses an Amiga M68K cross-compiler on linux or macOS. +# +# Cross-compiler: https://franke.ms/git/bebbo/amiga-gcc +# Install to /opt/amiga, then: +# sys/unix/setup.sh sys/unix/hints/linux.370 +# make fetch-lua +# make CROSS_TO_AMIGA=1 fetch-regex +# make CROSS_TO_AMIGA=1 all +# make CROSS_TO_AMIGA=1 package +#================================================================= + +CFLAGS += -DCROSSCOMPILE + +# +# Override the build tools and some obj files to +# reflect the amiga-gcc cross-compiler. +# +TOOLTOP = /opt/amiga/bin +TOOLARCH = -m68000 +override REGEXOBJ = $(TARGETPFX)posixregex.o +AMIREGEXOBJ = $(TARGETPFX)regcomp.o $(TARGETPFX)regexec.o \ + $(TARGETPFX)regerror.o $(TARGETPFX)regfree.o +override TARGET_CC = $(TOOLTOP)/m68k-amigaos-gcc +override TARGET_CXX = $(TOOLTOP)/m68k-amigaos-c++ +override TARGET_AR = $(TOOLTOP)/m68k-amigaos-ar +override TARGET_STUBEDIT= +override TARGET_CFLAGS = -c -O2 -noixemul $(TOOLARCH) \ + -include sys/types.h \ + -I../include \ + -I../sys/amiga -I../win/share \ + $(LUAINCL) -DAMIGA -DNOTTYGRAPHICS -DNO_TERMS -DNO_SIGNAL \ + -DTILES_IN_GLYPHMAP $(PDCURSESDEF) \ + -DCROSSCOMPILE -DCROSSCOMPILE_TARGET -DCROSS_TO_AMIGA \ + -DAMIGA_VERSION_STRING=\""VER: NetHack 3.7.0"\" +override TARGET_CXXFLAGS = $(TARGET_CFLAGS) +LUA_TARGET_CFLAGS = $(TARGET_CFLAGS) -DLUA_32BITS=1 +ifeq "$(REGEXOBJ)" "$(TARGETPFX)cppregex.o" +override TARGET_LINK = $(TARGET_CXX) +else +override TARGET_LINK = $(TARGET_CC) +endif +override TARGET_LFLAGS= $(TOOLARCH) -noixemul -Wl,--allow-multiple-definition +override TARGET_LIBS += $(LIBLM) +VARDATND += nhtiles.bmp +override SYSSRC = ../sys/amiga/amidos.c ../sys/amiga/amigst.c \ + ../sys/amiga/amimenu.c ../sys/amiga/amirip.c \ + ../sys/amiga/amistack.c ../sys/amiga/amitty.c \ + ../sys/amiga/amiwind.c ../sys/amiga/clipwin.c \ + ../sys/amiga/colorwin.c \ + ../sys/amiga/winami.c ../sys/amiga/winchar.c \ + ../sys/amiga/winfuncs.c ../sys/amiga/winkey.c \ + ../sys/amiga/winamenu.c ../sys/amiga/winreq.c \ + ../sys/amiga/winstr.c ../sys/share/pcmain.c \ + ../win/share/bmptiles.c ../win/share/giftiles.c \ + ../win/share/tileset.c +override SYSOBJ = $(TARGETPFX)amidos.o $(TARGETPFX)amigst.o \ + $(TARGETPFX)amirip.o $(TARGETPFX)amistack.o \ + $(TARGETPFX)amitty.o $(TARGETPFX)amiwind.o \ + $(TARGETPFX)winami.o $(TARGETPFX)winchar.o \ + $(TARGETPFX)winfuncs.o $(TARGETPFX)winkey.o \ + $(TARGETPFX)winamenu.o $(TARGETPFX)winreq.o \ + $(TARGETPFX)winstr.o $(TARGETPFX)pcmain.o \ + $(TARGETPFX)bmptiles.o $(TARGETPFX)giftiles.o \ + $(TARGETPFX)tileset.o \ + $(AMIREGEXOBJ) +override WINLIB= +override LUALIB= +override LUALIBS= +override TOPLUALIB= +override DLLIB= +override WINOBJ= +override GAMEBIN = $(TARGETPFX)nethack +override PACKAGE = amigapkg +override PREGAME += mkdir -p $(TARGETDIR) ; +override CLEANMORE += rm -r $(TARGETDIR) ; +# +# Rule for files in sys/amiga +$(TARGETPFX)%.o : ../sys/amiga/%.c + $(TARGET_CC) $(TARGET_CFLAGS) -o$@ $< +# Rule for BSD regex in sys/amiga/regex +$(TARGETPFX)%.o : ../sys/amiga/regex/%.c + $(TARGET_CC) $(TARGET_CFLAGS) -I../sys/amiga/regex -o$@ $< +endif # CROSS_TO_AMIGA +#================================================================= + ifdef WANT_WIN_CURSES ifdef BUILD_PDCURSES # Rules for PDCurses files