Merge branch 'amiga-port' of https://github.com/ingpaschke/NetHack into NetHack-3.7

This commit is contained in:
nhmall
2026-03-24 05:37:17 -04:00
42 changed files with 2053 additions and 914 deletions

2
.gitignore vendored
View File

@@ -96,3 +96,5 @@ bundle/*
util/*.lib
util/*.exp
submodules/CHKSUMS.tmp
sys/amiga/regex/
sys/amiga/regex/

View File

@@ -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

View File

@@ -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 */

View File

@@ -95,7 +95,7 @@
#undef UNIX
#define DLB
#define HACKDIR "NetHack:"
#define NO_MACRO_CPATH
#endif
/*

View File

@@ -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;

View File

@@ -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
};

View File

@@ -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)

View File

@@ -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__)

107
sys/amiga/README.amiga Normal file
View File

@@ -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: <path>
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.

View File

@@ -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 <intuition/intuition.h>
#undef COUNT
#if defined(__SASC_60) || defined(__GNUC__)
#include <proto/exec.h>
#include <proto/dos.h>
#endif
/* POSIX stubs needed by libnix (-noixemul) */
#ifdef __noixemul__
int getpid(void) { return (int)FindTask(NULL); }
#endif
#ifdef AZTEC_50
#include <functions.h>
#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 <bhaak@gmx.net> 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 = '_';

View File

@@ -43,15 +43,15 @@ static struct RastPort *rp;
#include <proto/diskfont.h>
#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;

View File

@@ -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<EFBFBD>rvi, Tampere, Finland, 2000 */
/* NetHack may be freely redistributed. See license for details. */
/*
@@ -12,10 +12,16 @@
#ifdef __SASC_60
#include <dos.h>
#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

View File

@@ -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;
}

View File

@@ -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 */

480
sys/amiga/bmp2iff_host.c Normal file
View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#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;
}

44
sys/amiga/nethack.cnf Normal file
View File

@@ -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

View File

@@ -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);

View File

@@ -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 <esc>, 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);

View File

@@ -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 );

View File

@@ -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 */

View File

@@ -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

View File

@@ -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))

View File

@@ -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...");

View File

@@ -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);

View File

@@ -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]);

View File

@@ -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");

346
sys/amiga/xpm2iff_host.c Normal file
View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
/* ------------------------------------------------------------------
* 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;
}

View File

@@ -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];

View File

@@ -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)

View File

@@ -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=

View File

@@ -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