The m4nfo User Manual and Report

Installation

Introduction

m4nfo is best suited for the large newGRF development projects, which usually consist of distributed source files and need some sort of project management. This requires additional software support, resulting into an 'advanced installation'. But of course, it is also possible to make use of m4nfo in a very basic way with only one m4nfo module each and grfcodec.

Description

Basic installation

After installation of M4 and grfcodec, you might have to set your $PATH / %PATH% variable in such a way that both programs are accessible from your working directory. Then, a command

M4 -R m4nfo_trains.m4 < test.nfx > test.nfo

should generate test.nfo from test.nfx, given that test.nfx is your m4nfo source file containing valid m4nfo code.

Since m4nfo header r91, different operating systems are supported by m4nfo functions cargotranslationtable() and export() which need the underlying OS to handle scratch files when working with distributed source files. The default is windows, to get the correct behaviour for Unix/OSX above command should be modified to

M4 -Dunix -R m4nfo_trains.m4 < test.nfx > test.nfo

Be aware that test.nfo does not include proper sprite numbers at this point. Because sprite numbers are indispensable for debugging, these have to be generated by a second run including file count.m4 (or count32.m4, both included in the m4nfo download package):

copy count.m4 + test.nfo test.tt (Windows)
or
cat count.m4 test.nfo > test.tt (Unix / OSX)
M4 < test.tt > test.nfo

You may then issue a last command

grfcodec -e test.grf

to generate the newGRF test.grf from both test.nfo and any associated graphics file(s),e.g. test.pcx or test.png.

It is recommended to put the needed commands into a batch file and thus be able to generate the newGRF by using only a single command:

Example (DOS/Windows):
m4.exe <sprites\%1.nfx >sprites\%1.nfo
copy count.m4 + sprites\%1.nfo test.tt
m4.exe <test.tt >sprites\%1.nfo
grfcodec.exe -e %1.grf
Example (Unix/OSX):
#!/bin/bash
m4 -Dunix <sprites/$1.nfx >sprites/$1.nfo
cat count.m4 sprites/$1.nfo >test.tt
m4 <test.tt >sprites/$1.nfo
grfcodec -e $1.grf

Please note:
m4nfo source files are ordinary text files and have a .nfx suffix. m4nfo include files (if any) are also ordinary text files, but are denoted by a .m4 suffix.

Advanced installation

After installation of M4, make, grfcodec, irfanview and pspad, you should set up an appropriate directory structure for your project.

Let's assume that the project will be a train set, called 'bluetrain'. In this case, you should set up a directory 'bluetrain' and include another directory 'sprites' in it. In addition, you need a file 'makefile' in directory 'bluetrain' to control the GNU 'make' utility. This directory could also contain project-related files such as a file 'names.m4' with the name/veh-ID mapping for all the train set's vehicles, or a general file 'bluetrain.m4' containing even more project-related stuff such as text strings, recolouring constants, custom error codes, cargo types, etc. Shown here are examples from my "DB Set" newGRF:

Example (names.m4):
define(_BR92,0x00)
define(_BR38,0x01)
define(_BR18,0x02)
define(_BR01,0x03)
define(_BR05,0x04)
define(_BR44,0x05)
define(_SVT137,0x06)
...

Example (dbxl.m4):
// M4 macros for DBXL 0.9
//	

// transparent sprite
define(VOID, 0xFE)

// shorthands
define(ALLOW,{cbr(1)})
define(DISALLOW,{cbr(0)})

// DBXL Parameters
define(_CAPACITIES,0)
define(_GATES,1)
define(_TANKLIVERY,2)
define(_STAKELIVERY,3)
define(_SEMAPHORES,4)
define(_DBRAILS,5)

// DBXL cargo aging values
define(PS_LOW,128)		// *1
define(PS_DEFAULT,256)		// *2
define(PS_MEDIUM,1152)		// *9
define(PS_HIGH,2048)		// *16
define(PS_HIGHER,3200)		// *25
define(PS_DELUXE,4608)		// *36
define(PS_DELUXEXL,6272)	// *49

// DBXL text constants
//
// TSF = SuffiX for cargoes
define(TSF_PGOOD,0x00)
define(TSF_CONT,0x01)
define(TSF_PLYW,0x02)
define(TSF_LIQU,0x03)
define(TSF_MACH,0x04)
...

// TSX = SuffiX for coaches
define(TSX_RHEINGOLD,0x20)
define(TSX_TEE,0x21)
define(TSX_IR,0x22)
define(TSX_IC,0x23)
define(TSX_SBAHN,0x24)
...

// TTS = Train Services / refittable coaches
define(TTS_RHEINGOLD,0x50)
define(TTS_FTRAIN,0x51)
define(TTS_RHEINGOLD2,0x52)
define(TTS_TEE,0x53)
define(TTS_IRIC,0x54)
...

// TLH = Locomotive Help texts
define(TLH_BR92,0xD0)
define(TLH_BR75,0xD1)
define(TLH_BR38,0xD2)
define(TLH_BR18,0xD3)
define(TLH_BR01,0xD4)
...

// constants for recolouring
//
// original colours / CB results
define(DBLUE,0x8307) 
define(LGREEN,0x8308)
define(PINK,0x8309)
define(YELLOW,0x830A)
define(RED,0x830B)
...

// error codes
//
define(ATT_OK,0xFE)
define(ATT_VAN,0x40)
define(ATT_CAR,0x41)
define(ATT_REQLDCAR,0x42)
define(ATT_CARBADNUM,0x43)
...

Directory 'sprites' will hold all the graphics files for the project, as well as all the m4nfo source files (~.nfx).

Now, the core of the system is the 'makefile' which will control the 'make' utility in such a way that the project will be updated in a proper way, whatever files have been worked on since the last update. E.g., if the project includes 4 source files bluetrain_1.nfx .. bluetrain4.nfx, and the graphics file for an engine 'VT_001.bmp' which is addressed from 'bluetrain_3.nfx' would have been updated since the last run, 'make' would start the graphics conversion utility to convert 'VT_001.bmp' to 'VT_001.pcx', and then start grfcodec to build the newGRF.

Likewise, if there have been changes in 'bluetrain_2.nfx' since the last run, 'make' would start M4 to compile 'bluetrain_2.nfo' from 'bluetrain_2.nfx', and then start grfcodec to build the newGRF.

In this way, only the files which have been updated are used to build a newGRF.

Here is a prototypical makefile for the above-mentioned project:

Example (makefile):
# 'bluetrain' makefile

V = sprites\bluetrain

# include macro files, header, trains, names etc
INCS = bluetrain.m4 names.m4

# .nfo target files
NFOFILES =  $V_0.nfo $V_1.nfo $V_2.nfo $V_3.nfo $V_4.nfo  

# graphics source files
BMPDIR = bluetrain/sprites/
PCXFILES := $(patsubst %.bmp,%.pcx,$(subst /,\,$(wildcard $(BMPDIR)*.bmp)))

# M4 text processor
M4 = c:\programs\m4gnuw32\bin\m4.exe

# grfcodec program
GRFCODEC = c:\mpstest\ttdlx\grfcodec.exe
GRFCODECFLAGS = -e -m0

# irfanview program
IVIEW = c:\programs\iview351\i_view32.exe

# rule to make .nfo from .nfx
%.nfo : %.nfx $(INCS)
	$(M4) $< > $@

# rule to make .pcx from .bmp
%.pcx : %.bmp 
	$(IVIEW) < /convert=$@ 

# rule to make test.grf from .nfo and .pcx
test.grf : $(PCXFILES) $(NFOFILES)
        copy count.m4 + $(strip $(NFOFILES)) sprites\test.tt
        $(M4)<sprites\test.tt >sprites\test.nfo
	$(GRFCODEC) $(GRFCODECFLAGS) test.grf 
	copy test.grf C:\ttdxwin\newgrf\bluetrainw.grf
	copy test.grf C:\mpstest\ottd\data\bluetrainw.grf

all: test.grf

Here's neither time nor room to explain makefiles in general, so you should take a look into makes's documentation.

Now, the best thing is that this makefile can be activated by starting 'make' from the editor, e.g. in PSPAD by clicking the button 'start compiler'!