summaryrefslogtreecommitdiff
path: root/grfspecial.c
diff options
context:
space:
mode:
authordarkvater <darkvater@openttd.org>2004-11-12 18:57:46 +0000
committerdarkvater <darkvater@openttd.org>2004-11-12 18:57:46 +0000
commitc53cf38ffdf56d79e9de36182a146c90c38c1edb (patch)
tree2a3963bc101de95fd040e7780d6e662777fe718c /grfspecial.c
parent16f8a7b2d2e51b5f1ee1203f56dfef5d2e912941 (diff)
downloadopenttd-c53cf38ffdf56d79e9de36182a146c90c38c1edb.tar.xz
(svn r550) -newgrf: Support for action 0xd (change a parameter (sorta variable for the GRF scripts)). Based on patch by octo, heavy changes by pasky.
Diffstat (limited to 'grfspecial.c')
-rw-r--r--grfspecial.c103
1 files changed, 101 insertions, 2 deletions
diff --git a/grfspecial.c b/grfspecial.c
index 1f00d052e..ae915ae4c 100644
--- a/grfspecial.c
+++ b/grfspecial.c
@@ -23,6 +23,9 @@ extern int _replace_sprites_offset[16];
static const char *_cur_grffile;
static int _cur_spriteid;
+static int32 _paramlist[0x7f];
+static int _param_max;
+
typedef void (*SpecialSpriteHandler)(byte *buf, int len);
static const int _vehshifts[4] = {
@@ -899,7 +902,13 @@ static void SkipIf(byte *buf, int len)
param_val = _opt.road_side << 4;
break;
default:
- grfmsg(GMS_WARN, "Unsupported param %x. Ignoring test.", param);
+ if (param >= 0x80) {
+ /* In-game variable. */
+ grfmsg(GMS_WARN, "Unsupported in-game variable %x. Ignoring test.", param);
+ } else {
+ /* Parameter. */
+ param_val = _paramlist[param];
+ }
return;
}
@@ -1065,7 +1074,97 @@ static void ParamSet(byte *buf, int len)
* 06 Signed bit shift, source1 by source2
* (source2 like in 05, and source1 as well)
*/
- /* TODO */
+
+ byte target;
+ byte oper;
+ uint16 src1;
+ uint16 src2;
+ uint16 data = 0;
+
+ check_length(len, 5, "ParamSet");
+ target = grf_load_byte(&buf);
+ oper = grf_load_byte(&buf);
+ src1 = grf_load_byte(&buf);
+ src2 = grf_load_byte(&buf);
+
+ if (len >= 8)
+ data = grf_load_dword(&buf);
+
+ /* You can add 80 to the operation to make it apply only if the target
+ * is not defined yet. In this respect, a parameter is taken to be
+ * defined if any of the following applies:
+ * - it has been set to any value in the newgrf(w).cfg parameter list
+ * - it OR A PARAMETER WITH HIGHER NUMBER has been set to any value by
+ * an earlier action D */
+ if (oper & 0x80) {
+ if (_param_max < target)
+ oper &= 0x7F;
+ else
+ return;
+ }
+
+ /* The source1 and source2 operands refer to the grf parameter number
+ * like in action 6 and 7. In addition, they can refer to the special
+ * variables available in action 7, or they can be FF to use the value
+ * of <data>. If referring to parameters that are undefined, a value
+ * of 0 is used instead. */
+ if (src1 == 0xFF) {
+ src1 = data;
+ } else {
+ src1 = _param_max >= src1 ? _paramlist[src1] : 0;
+ }
+
+ if (src2 == 0xFF) {
+ src2 = data;
+ } else {
+ src2 = _param_max >= src2 ? _paramlist[src2] : 0;
+ }
+
+ /* TODO: You can access the parameters of another GRF file by using
+ * source2=FE, source1=the other GRF's parameter number and data=GRF
+ * ID. This is only valid with operation 00 (set). If the GRF ID
+ * cannot be found, a value of 0 is used for the parameter value
+ * instead. */
+
+ /* TODO: The target operand can also refer to the special variables
+ * from action 7, but at the moment the only variable that is valid to
+ * write is 8E. */
+
+ if (_param_max < target)
+ _param_max = target;
+
+ /* FIXME: No checking for overflows. */
+ switch (oper) {
+ case 0x00:
+ _paramlist[target] = src1;
+ break;
+ case 0x01:
+ _paramlist[target] = src1 + src2;
+ break;
+ case 0x02:
+ _paramlist[target] = src1 - src2;
+ break;
+ case 0x03:
+ _paramlist[target] = ((uint32) src1) * ((uint32) src2);
+ break;
+ case 0x04:
+ _paramlist[target] = ((int32) src1) * ((int32) src2);
+ break;
+ case 0x05:
+ if (src2 & 0x8000) /* src2 is "negative" */
+ _paramlist[target] = src1 >> -((int16) src2);
+ else
+ _paramlist[target] = src1 << src2;
+ break;
+ case 0x06:
+ if (src2 & 0x8000) /* src2 is "negative" */
+ _paramlist[target] = ((int16) src1) >> -((int16) src2);
+ else
+ _paramlist[target] = ((int16) src1) << src2;
+ break;
+ default:
+ grfmsg(GMS_ERROR, "ParamSet: Unknown operation %d, skipping.", oper);
+ }
}
static void GRFInhibit(byte *buf, int len)