1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "agi/agi.h"
24 #include "agi/opcodes.h"
25 
26 namespace Agi {
27 
28 const AgiOpCodeDefinitionEntry opCodesV1Cond[] = {
29 	{ "",                   "",         &condUnknown },     // 00
30 	{ "equaln",             "vn",       &condEqual },       // 01
31 	{ "equalv",             "vv",       &condEqualV },      // 02
32 	{ "lessn",              "vn",       &condLess },        // 03
33 	{ "lessv",              "vv",       &condLessV },       // 04
34 	{ "greatern",           "vn",       &condGreater },     // 05
35 	{ "greaterv",           "vv",       &condGreaterV },    // 06
36 	{ "isset",              "v",        &condIsSetV1 },     // 07
37 	{ "has",                "n",        &condHasV1 },       // 08
38 	{ "said",               "nnnn",     &condSaid2 },       // 09
39 	{ "posn",               "nnnnn",    &condPosn },        // 0A
40 	{ "controller",         "n",        &condController },  // 0B
41 	{ "obj.in.room",        "nv",       &condObjInRoom },   // 0C
42 	{ "said",               "nnnnnn",   &condSaid3 },       // 0D
43 	{ "have.key",           "",         &condHaveKey },     // 0E
44 	{ "said",               "nn",       &condSaid1 },       // 0F
45 	{ "bit",                "nv",       &condBit },         // 10
46 };
47 
48 const AgiOpCodeDefinitionEntry opCodesV1[] = {
49 	{ "return",             "",         NULL },                 // 00
50 	{ "increment",          "v",        &cmdIncrement },        // 01
51 	{ "decrement",          "v",        &cmdDecrement },        // 02
52 	{ "assignn",            "vn",       &cmdAssignN },          // 03
53 	{ "assignv",            "vv",       &cmdAssignV },          // 04
54 	{ "addn",               "vn",       &cmdAddN },             // 05
55 	{ "addv",               "vv",       &cmdAddV },             // 06
56 	{ "subn",               "vn",       &cmdSubN },             // 07
57 	{ "subv",               "vv",       &cmdSubV },             // 08
58 	{ "load.view",          "n",        &cmdLoadView },         // 09
59 	{ "animate.obj",        "n",        &cmdAnimateObj },       // 0A
60 	{ "new.room",           "n",        &cmdNewRoom },          // 0B
61 	{ "draw.pic",           "v",        &cmdDrawPicV1 },        // 0C
62 	{ "print",              "s",        &cmdPrint },            // 0D TODO
63 	{ "status",             "",         &cmdStatus },           // 0E TODO
64 	{ "save.game",          "",         &cmdSaveGame },         // 0F TODO
65 	{ "restore.game",       "",         &cmdLoadGame },         // 10 TODO
66 	{ "init.disk",          "",         &cmdInitDisk },         // 11 TODO
67 	{ "restart.game",       "",         &cmdRestartGame },      // 12 TODO
68 	{ "random",             "v",        &cmdRandomV1 },         // 13
69 	{ "get",                "n",        &cmdGetV1 },            // 14
70 	{ "drop",               "n",        &cmdDrop },             // 15
71 	{ "draw",               "n",        &cmdDraw },             // 16 TODO
72 	{ "erase",              "n",        &cmdErase },            // 17 TODO
73 	{ "position",           "nnn",      &cmdPositionV1 },       // 18
74 	{ "position.v",         "nvv",      &cmdPositionFV1 },      // 19
75 	{ "get.posn",           "nvv",      &cmdGetPosn },          // 1A
76 	{ "set.cel",            "nn",       &cmdSetCel },           // 1B
77 	{ "set.loop",           "nn",       &cmdSetLoop },          // 1C
78 	{ "end.of.loop",        "nn",       &cmdEndOfLoopV1 },      // 1D
79 	{ "reverse.loop",       "nn",       &cmdReverseLoopV1 },    // 1E
80 	{ "move.obj",           "nnnnn",    &cmdMoveObj },          // 1F
81 	{ "set.view",           "nn",       &cmdSetView },          // 20
82 	{ "follow.ego",         "nnn",      &cmdFollowEgo },        // 21
83 	{ "block",              "",         &cmdBlock },            // 22
84 	{ "unblock",            "",         &cmdUnblock },          // 23
85 	{ "ignore.blocks",      "n",        &cmdIgnoreBlocks },     // 24
86 	{ "observe.blocks",     "n",        &cmdObserveBlocks },    // 25
87 	{ "wander",             "n",        &cmdWander },           // 26
88 	{ "reposition",         "nvv",      &cmdRepositionV1 },     // 27
89 	{ "stop.motion",        "n",        &cmdStopMotionV1 },     // 28
90 	{ "start.motion",       "n",        &cmdStartMotionV1 },    // 29
91 	{ "stop.cycling",       "n",        &cmdStopCycling },      // 2A
92 	{ "start.cycling",      "n",        &cmdStartCycling },     // 2B
93 	{ "stop.update",        "n",        &cmdStopUpdate },       // 2C
94 	{ "start.update",       "n",        &cmdStartUpdate },      // 2D
95 	{ "program.control",    "",         &cmdProgramControl },   // 2E
96 	{ "player.control",     "",         &cmdPlayerControl },    // 2F
97 	{ "set.priority",       "nn",       &cmdSetPriority },      // 30
98 	{ "release.priority",   "n",        &cmdReleasePriority },  // 31
99 	{ "add.to.pic",         "nnnnnn",   &cmdAddToPicV1 },       // 32
100 	{ "set.horizon",        "n",        &cmdSetHorizon },       // 33
101 	{ "ignore.horizon",     "n",        &cmdIgnoreHorizon },    // 34
102 	{ "observe.horizon",    "n",        &cmdObserveHorizon },   // 35
103 	{ "load.logics",        "n",        &cmdLoadLogic },        // 36 TODO
104 	{ "object.on.water",    "n",        &cmdObjectOnWater },    // 37
105 	{ "load.pic",           "v",        &cmdLoadPicV1 },        // 38
106 	{ "load.sound",         "n",        &cmdLoadSound },        // 39
107 	{ "sound",              "nn",       &cmdSound },            // 3A
108 	{ "stop.sound",         "",         &cmdStopSound },        // 3B
109 	{ "set.v",              "v",        &cmdSetV },             // 3C
110 	{ "reset.v",            "v",        &cmdResetV },           // 3D
111 	{ "toggle.v",           "v",        &cmdToggleV },          // 3E
112 	{ "new.room.v",         "v",        &cmdNewRoom },          // 3F
113 	{ "call",               "n",        &cmdCallV1 },           // 40 TODO
114 	{ "quit",               "",         &cmdQuitV1 },           // 41
115 	{ "set.speed",          "v",        &cmdSetSpeed },         // 42
116 	{ "move.obj.v",         "nvvvv",    &cmdMoveObjF },         // 43
117 	{ "...",                "nn",       &cmdUnknown },          // 44
118 	{ "get.v",              "v",        &cmdUnknown },          // 45
119 	{ "assign.v",           "vv",       &cmdUnknown },          // 46
120 	{ "...",                "n",        &cmdUnknown },          // 47 # printvar.v
121 	{ "get.priority",       "nv",       &cmdGetPriority },      // 48
122 	{ "ignore.objs",        "n",        &cmdIgnoreObjs },       // 49
123 	{ "observe.objs",       "n",        &cmdObserveObjs },      // 4A
124 	{ "distance",           "nnv",      &cmdDistance },         // 4B
125 	{ "object.on.land",     "n",        &cmdObjectOnLand },     // 4C
126 	{ "...",                "nv",       &cmdUnknown },          // 4D # set.priority.f
127 	{ "...",                "",         &cmdUnknown },          // 4E  # show.obj
128 	{ "load.logics",        "n",        &cmdLoadLogic },        // 4F # load.global.logics
129 	{ "display",            "nnns",     &cmdDisplay },          // 50 TODO: 4 vs 3 args
130 	{ "prevent.input???",   "",         &cmdUnknown },          // 51
131 	{ "...",                "",         &cmdUnknown },          // 52 # nop
132 	{ "...",                "n",        &cmdUnknown },          // 53 # text.screen
133 	{ "...",                "",         &cmdUnknown },          // 54 ???
134 	{ "stop.motion",        "",         &cmdStopMotion },       // 55 or force.update??
135 	{ "discard.view",       "n",        &cmdDiscardView },      // 56
136 	{ "discard.pic",        "v",        &cmdDiscardPic },       // 57
137 	{ "set.item.view",      "nn",       &cmdSetItemView },      // 58
138 	{ "...",                "",         &cmdUnknown },          // 59 # reverse.cycle
139 	{ "last.cel",           "nv",       &cmdLastCel },          // 5A
140 	{ "set.cel.v",          "nv",       &cmdSetCelF },          // 5B
141 	{ "...",                "",         &cmdUnknown },          // 5C # normal.cycle
142 	{ "load.view",          "n",        &cmdLoadView },         // 5D
143 	{ "...",                "",         &cmdUnknown },          // 5E
144 	{ "...",                "",         &cmdUnknown },          // 5F
145 	{ "setbit",             "nv",       &cmdUnknown },          // 60
146 	{ "...",                "nv",       &cmdUnknown },          // 61 # clearbit
147 };
148 
149 AgiOpCodeDefinitionEntry opCodesV2Cond[] = {
150 	{ "",                   "",         &condUnknown },         // 00
151 	{ "equaln",             "vn",       &condEqual },           // 01
152 	{ "equalv",             "vv",       &condEqualV },          // 02
153 	{ "lessn",              "vn",       &condLess },            // 03
154 	{ "lessv",              "vv",       &condLessV },           // 04
155 	{ "greatern",           "vn",       &condGreater },         // 05
156 	{ "greaterv",           "vv",       &condGreaterV },        // 06
157 	{ "isset",              "n",        &condIsSet },           // 07
158 	{ "issetv",             "v",        &condIsSetV },          // 08
159 	{ "has",                "n",        &condHas },             // 09
160 	{ "obj.in.room",        "nv",       &condObjInRoom},        // 0A
161 	{ "posn",               "nnnnn",    &condPosn },            // 0B
162 	{ "controller",         "n",        &condController },      // 0C
163 	{ "have.key",           "",         &condHaveKey},          // 0D
164 	{ "said",               "",         &condSaid },            // 0E
165 	{ "compare.strings",    "ss",       &condCompareStrings },  // 0F
166 	{ "obj.in.box",         "nnnnn",    &condObjInBox },        // 10
167 	{ "center.posn",        "nnnnn",    &condCenterPosn },      // 11
168 	{ "right.posn",         "nnnnn",    &condRightPosn },       // 12
169 	{ "in.motion.using.mouse", "",      &condUnknown13 }        // 13
170 };
171 
172 AgiOpCodeDefinitionEntry opCodesV2[] = {
173 	{ "return",             "",         NULL },                 // 00
174 	{ "increment",          "v",        &cmdIncrement },        // 01
175 	{ "decrement",          "v",        &cmdDecrement },        // 02
176 	{ "assignn",            "vn",       &cmdAssignN },          // 03
177 	{ "assignv",            "vv",       &cmdAssignV },          // 04
178 	{ "addn",               "vn",       &cmdAddN },             // 05
179 	{ "addv",               "vv",       &cmdAddV },             // 06
180 	{ "subn",               "vn",       &cmdSubN },             // 07
181 	{ "subv",               "vv",       &cmdSubV },             // 08
182 	{ "lindirectv",         "vv",       &cmdLindirectV },       // 09
183 	{ "lindirect",          "vv",       &cmdRindirect },        // 0A
184 	{ "lindirectn",         "vn",       &cmdLindirectN },       // 0B
185 	{ "set",                "n",        &cmdSet },              // 0C
186 	{ "reset",              "n",        &cmdReset },            // 0D
187 	{ "toggle",             "n",        &cmdToggle },           // 0E
188 	{ "set.v",              "v",        &cmdSetV },             // 0F
189 	{ "reset.v",            "v",        &cmdResetV },           // 10
190 	{ "toggle.v",           "v",        &cmdToggleV },          // 11
191 	{ "new.room",           "n",        &cmdNewRoom },          // 12
192 	{ "new.room.v",         "v",        &cmdNewRoomF },         // 13
193 	{ "load.logics",        "n",        &cmdLoadLogic },        // 14
194 	{ "load.logics.v",      "v",        &cmdLoadLogicF },       // 15
195 	{ "call",               "n",        &cmdCall },             // 16
196 	{ "call.v",             "v",        &cmdCallF },            // 17
197 	{ "load.pic",           "v",        &cmdLoadPic },          // 18
198 	{ "draw.pic",           "v",        &cmdDrawPic },          // 19
199 	{ "show.pic",           "",         &cmdShowPic },          // 1A
200 	{ "discard.pic",        "v",        &cmdDiscardPic },       // 1B
201 	{ "overlay.pic",        "v",        &cmdOverlayPic },       // 1C
202 	{ "show.pri.screen",    "",         &cmdShowPriScreen },    // 1D
203 	{ "load.view",          "n",        &cmdLoadView },         // 1E
204 	{ "load.view.v",        "v",        &cmdLoadViewF },        // 1F
205 	{ "discard.view",       "n",        &cmdDiscardView },      // 20
206 	{ "animate.obj",        "n",        &cmdAnimateObj },       // 21
207 	{ "unanimate.all",      "",         &cmdUnanimateAll },     // 22
208 	{ "draw",               "n",        &cmdDraw },             // 23
209 	{ "erase",              "n",        &cmdErase },            // 24
210 	{ "position",           "nnn",      &cmdPosition },         // 25
211 	{ "position.v",         "nvv",      &cmdPositionF },        // 26
212 	{ "get.posn",           "nvv",      &cmdGetPosn },          // 27
213 	{ "reposition",         "nvv",      &cmdReposition },       // 28
214 	{ "set.view",           "nn",       &cmdSetView },          // 29
215 	{ "set.view.v",         "nv",       &cmdSetViewF },         // 2A
216 	{ "set.loop",           "nn",       &cmdSetLoop },          // 2B
217 	{ "set.loop.v",         "nv",       &cmdSetLoopF },         // 2C
218 	{ "fix.loop",           "n",        &cmdFixLoop },          // 2D
219 	{ "release.loop",       "n",        &cmdReleaseLoop },      // 2E
220 	{ "set.cel",            "nn",       &cmdSetCel },           // 2F
221 	{ "set.cel.v",          "nv",       &cmdSetCelF },          // 30
222 	{ "last.cel",           "nv",       &cmdLastCel },          // 31
223 	{ "current.cel",        "nv",       &cmdCurrentCel },       // 32
224 	{ "current.loop",       "nv",       &cmdCurrentLoop },      // 33
225 	{ "current.view",       "nv",       &cmdCurrentView },      // 34
226 	{ "number.of.loops",    "nv",       &cmdNumberOfLoops },    // 35
227 	{ "set.priority",       "nn",       &cmdSetPriority },      // 36
228 	{ "set.priority.v",     "nv",       &cmdSetPriorityF },     // 37
229 	{ "release.priority",   "n",        &cmdReleasePriority },  // 38
230 	{ "get.priority",       "nn",       &cmdGetPriority },      // 39
231 	{ "stop.update",        "n",        &cmdStopUpdate },       // 3A
232 	{ "start.update",       "n",        &cmdStartUpdate },      // 3B
233 	{ "force.update",       "n",        &cmdForceUpdate },      // 3C
234 	{ "ignore.horizon",     "n",        &cmdIgnoreHorizon },    // 3D
235 	{ "observe.horizon",    "n",        &cmdObserveHorizon },   // 3E
236 	{ "set.horizon",        "n",        &cmdSetHorizon },       // 3F
237 	{ "object.on.water",    "n",        &cmdObjectOnWater },    // 40
238 	{ "object.on.land",     "n",        &cmdObjectOnLand },     // 41
239 	{ "object.on.anything", "n",        &cmdObjectOnAnything }, // 42
240 	{ "ignore.objs",        "n",        &cmdIgnoreObjs },       // 43
241 	{ "observe.objs",       "n",        &cmdObserveObjs },      // 44
242 	{ "distance",           "nnv",      &cmdDistance },         // 45
243 	{ "stop.cycling",       "n",        &cmdStopCycling },      // 46
244 	{ "start.cycling",      "n",        &cmdStartCycling },     // 47
245 	{ "normal.cycle",       "n",        &cmdNormalCycle },      // 48
246 	{ "end.of.loop",        "nn",       &cmdEndOfLoop },        // 49
247 	{ "reverse.cycle",      "n",        &cmdReverseCycle },     // 4A
248 	{ "reverse.loop",       "nn",       &cmdReverseLoop },      // 4B
249 	{ "cycle.time",         "nv",       &cmdCycleTime },        // 4C
250 	{ "stop.motion",        "n",        &cmdStopMotion },       // 4D
251 	{ "start.motion",       "n",        &cmdStartMotion },      // 4E
252 	{ "step.size",          "nv",       &cmdStepSize },         // 4F
253 	{ "step.time",          "nv",       &cmdStepTime },         // 50
254 	{ "move.obj",           "nnnnn",    &cmdMoveObj },          // 51
255 	{ "move.obj.v",         "nvvvv",    &cmdMoveObjF },         // 52
256 	{ "follow.ego",         "nnn",      &cmdFollowEgo },        // 53
257 	{ "wander",             "n",        &cmdWander },           // 54
258 	{ "normal.motion",      "n",        &cmdNormalMotion },     // 55
259 	{ "set.dir",            "nv",       &cmdSetDir },           // 56
260 	{ "get.dir",            "nv",       &cmdGetDir },           // 57
261 	{ "ignore.blocks",      "n",        &cmdIgnoreBlocks },     // 58
262 	{ "observe.blocks",     "n",        &cmdObserveBlocks },    // 59
263 	{ "block",              "nnnn",     &cmdBlock },            // 5A
264 	{ "unblock",            "",         &cmdUnblock },          // 5B
265 	{ "get",                "n",        &cmdGet },              // 5C
266 	{ "get.v",              "v",        &cmdGetF },             // 5D
267 	{ "drop",               "n",        &cmdDrop },             // 5E
268 	{ "put",                "nn",       &cmdPut },              // 5F
269 	{ "put.v",              "vv",       &cmdPutF },             // 60
270 	{ "get.room.v",         "vv",       &cmdGetRoomF },         // 61
271 	{ "load.sound",         "n",        &cmdLoadSound },        // 62
272 	{ "sound",              "nn",       &cmdSound },            // 63
273 	{ "stop.sound",         "",         &cmdStopSound },        // 64
274 	{ "print",              "s",        &cmdPrint },            // 65
275 	{ "print.v",            "v",        &cmdPrintF },           // 66
276 	{ "display",            "nns",      &cmdDisplay },          // 67
277 	{ "display.v",          "vvv",      &cmdDisplayF },         // 68
278 	{ "clear.lines",        "nns",      &cmdClearLines },       // 69
279 	{ "text.screen",        "",         &cmdTextScreen },       // 6A
280 	{ "graphics",           "",         &cmdGraphics },         // 6B
281 	{ "set.cursor.char",    "s",        &cmdSetCursorChar },    // 6C
282 	{ "set.text.attribute", "nn",       &cmdSetTextAttribute }, // 6D
283 	{ "shake.screen",       "n",        &cmdShakeScreen },      // 6E
284 	{ "configure.screen",   "nnn",      &cmdConfigureScreen },  // 6F
285 	{ "status.line.on",     "",         &cmdStatusLineOn },     // 70
286 	{ "status.line.off",    "",         &cmdStatusLineOff },    // 71
287 	{ "set.string",         "ns",       &cmdSetString },        // 72
288 	{ "get.string",         "nsnnn",    &cmdGetString },        // 73
289 	{ "word.to.string",     "nn",       &cmdWordToString },     // 74
290 	{ "parse",              "n",        &cmdParse },            // 75
291 	{ "get.num",            "nv",       &cmdGetNum },           // 76
292 	{ "prevent.input",      "",         &cmdPreventInput },     // 77
293 	{ "accept.input",       "",         &cmdAcceptInput },      // 78
294 	{ "set.key",            "nnn",      &cmdSetKey },           // 79
295 	{ "add.to.pic",         "nnnnnnn",  &cmdAddToPic },         // 7A
296 	{ "add.to.pic.v",       "vvvvvvv",  &cmdAddToPicF },        // 7B
297 	{ "status",             "",         &cmdStatus },           // 7C
298 	{ "save.game",          "",         &cmdSaveGame },         // 7D
299 	{ "restore.game",       "",         &cmdLoadGame },         // 7E
300 	{ "init.disk",          "",         &cmdInitDisk },         // 7F
301 	{ "restart.game",       "",         &cmdRestartGame },      // 80
302 	{ "show.obj",           "n",        &cmdShowObj },          // 81
303 	{ "random",             "nnv",      &cmdRandom },           // 82
304 	{ "program.control",    "",         &cmdProgramControl },   // 83
305 	{ "player.control",     "",         &cmdPlayerControl },    // 84
306 	{ "obj.status.v",       "v",        &cmdObjStatusF },       // 85
307 	{ "quit",               "n",        &cmdQuit },             // 86 0 args for AGI version 2.089
308 	{ "show.mem",           "",         &cmdShowMem },          // 87
309 	{ "pause",              "",         &cmdPause },            // 88
310 	{ "echo.line",          "",         &cmdEchoLine },         // 89
311 	{ "cancel.line",        "",         &cmdCancelLine },       // 8A
312 	{ "init.joy",           "",         &cmdInitJoy },          // 8B
313 	{ "toggle.monitor",     "",         &cmdToggleMonitor },    // 8C
314 	{ "version",            "",         &cmdVersion },          // 8D
315 	{ "script.size",        "n",        &cmdScriptSize },       // 8E
316 	{ "set.game.id",        "s",        &cmdSetGameID },        // 8F
317 	{ "log",                "s",        &cmdLog },              // 90
318 	{ "set.scan.start",     "",         &cmdSetScanStart },     // 91
319 	{ "reset.scan.start",   "",         &cmdResetScanStart },   // 92
320 	{ "reposition.to",      "nnn",      &cmdRepositionTo },     // 93
321 	{ "reposition.to.v",    "nvv",      &cmdRepositionToF },    // 94
322 	{ "trace.on",           "",         &cmdTraceOn },          // 95
323 	{ "trace.info",         "nnn",      &cmdTraceInfo },        // 96
324 	{ "print.at",           "snnn",     &cmdPrintAt }, // 3 args for AGI versions before 2.440
325 	{ "print.at.v",         "vnnn",     &cmdPrintAtV },         // 98
326 	{ "discard.view.v",     "v",        &cmdDiscardView},       // 99
327 	{ "clear.text.rect",    "nnnnn",    &cmdClearTextRect },    // 9A
328 	{ "set.upper.left",     "nn",       &cmdSetUpperLeft },     // 9B
329 	{ "set.menu",           "s",        &cmdSetMenu },          // 9C
330 	{ "set.menu.item",      "sn",       &cmdSetMenuItem },      // 9D
331 	{ "submit.menu",        "",         &cmdSubmitMenu },       // 9E
332 	{ "enable.item",        "n",        &cmdEnableItem },       // 9F
333 	{ "disable.item",       "n",        &cmdDisableItem },      // A0
334 	{ "menu.input",         "",         &cmdMenuInput },        // A1
335 	{ "show.obj.v",         "v",        &cmdShowObjV },         // A2
336 	{ "open.dialogue",      "",         &cmdOpenDialogue },     // A3
337 	{ "close.dialogue",     "",         &cmdCloseDialogue },    // A4
338 	{ "mul.n",              "vn",       &cmdMulN },             // A5
339 	{ "mul.v",              "vv",       &cmdMulV },             // A6
340 	{ "div.n",              "vn",       &cmdDivN },             // A7
341 	{ "div.v",              "vv",       &cmdDivV },             // A8
342 	{ "close.window",       "",         &cmdCloseWindow },      // A9
343 	{ "set.simple",         "n",        &cmdSetSimple },        // AA AGI2.425+, *BUT* not included in AGI2.440
344 	{ "push.script",        "",         &cmdPushScript },       // AB
345 	{ "pop.script",         "",         &cmdPopScript },        // AC
346 	{ "hold.key",           "",         &cmdHoldKey },          // AD
347 	{ "set.pri.base",       "n",        &cmdSetPriBase },       // AE AGI2.936+ *AND* also inside AGI2.425
348 	{ "discard.sound",      "n",        &cmdDiscardSound },     // AF was skip for PC
349 	{ "hide.mouse",         "",         &cmdHideMouse },        // B0 1 arg for AGI version 3.002.086 AGI3+ only starts here
350 	{ "allow.menu",         "n",        &cmdAllowMenu },        // B1
351 	{ "show.mouse",         "",         &cmdShowMouse },        // B2
352 	{ "fence.mouse",        "nnnn",     &cmdFenceMouse },       // B3
353 	{ "mouse.posn",         "vv",       &cmdMousePosn },        // B4
354 	{ "release.key",        "",         &cmdReleaseKey },       // B5 2 args for at least the Amiga GR (v2.05 1989-03-09) using AGI 2.316
355 	{ "adj.ego.move.to.xy", "",         &cmdAdjEgoMoveToXY }    // B6
356 };
357 
358 //
359 // Currently, there is no known difference between v3.002.098 -> v3.002.149
360 // So version emulated;
361 // 0x0086,
362 // 0x0149
363 //
364 
setupOpCodes(uint16 version)365 void AgiEngine::setupOpCodes(uint16 version) {
366 	const AgiOpCodeDefinitionEntry *opCodesTable = nullptr;
367 	const AgiOpCodeDefinitionEntry *opCodesCondTable = nullptr;
368 	uint16 opCodesTableSize = 0;
369 	uint16 opCodesCondTableSize = 0;
370 	uint16 opCodesTableMaxSize = sizeof(_opCodes) / sizeof(AgiOpCodeEntry);
371 	uint16 opCodesCondTableMaxSize = sizeof(_opCodesCond) / sizeof(AgiOpCodeEntry);
372 
373 	debug(0, "Setting up for version 0x%04X", version);
374 
375 	if (version >= 0x2000) {
376 		opCodesTable = opCodesV2;
377 		opCodesCondTable = opCodesV2Cond;
378 		opCodesTableSize = ARRAYSIZE(opCodesV2);
379 		opCodesCondTableSize = ARRAYSIZE(opCodesV2Cond);
380 	} else {
381 		opCodesTable = opCodesV1;
382 		opCodesCondTable = opCodesV1Cond;
383 		opCodesTableSize = ARRAYSIZE(opCodesV1);
384 		opCodesCondTableSize = ARRAYSIZE(opCodesV1Cond);
385 	}
386 
387 	// copy data over
388 	for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
389 		_opCodes[opCodeNr].name = opCodesTable[opCodeNr].name;
390 		_opCodes[opCodeNr].parameters = opCodesTable[opCodeNr].parameters;
391 		_opCodes[opCodeNr].functionPtr = opCodesTable[opCodeNr].functionPtr;
392 	}
393 
394 	for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
395 		_opCodesCond[opCodeNr].name = opCodesCondTable[opCodeNr].name;
396 		_opCodesCond[opCodeNr].parameters = opCodesCondTable[opCodeNr].parameters;
397 		_opCodesCond[opCodeNr].functionPtr = opCodesCondTable[opCodeNr].functionPtr;
398 	}
399 
400 	// Alter opcode parameters for specific games
401 	if ((version >= 0x2000) && (version < 0x3000)) {
402 		// AGI3 adjustments
403 
404 		// 'quit' takes 0 args for 2.089
405 		if (version == 0x2089)
406 			_opCodes[0x86].parameters = "";
407 
408 		// 'print.at' and 'print.at.v' take 3 args before 2.272
409 		// This is documented in the specs as only < 2.440, but it seems
410 		// that KQ3 (2.272) needs a 'print.at' taking 4 args.
411 		if (version < 0x2272) {
412 			_opCodes[0x97].parameters = "vvv";
413 			_opCodes[0x98].parameters = "vvv";
414 		}
415 	}
416 
417 	if (version >= 0x3000) {
418 		// AGI3 adjustments
419 		// 'unknown176' takes 1 arg for 3.002.086, not 0 args.
420 		// 'unknown173' also takes 1 arg for 3.002.068, not 0 args.
421 		// Is this actually used anywhere? -- dsymonds
422 		if (version == 0x3086) {
423 			_opCodes[0xb0].parameters = "n";
424 			_opCodes[0xad].parameters = "n";
425 		}
426 	}
427 
428 	// TODO: This could be either turned into a game feature, or a version
429 	// specific check, instead of a game version check
430 	// The Apple IIGS versions of MH1 and Goldrush both have a parameter for
431 	// show.mouse and hide.mouse. Fixes bugs #6161 and #5885.
432 	if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
433 	        getPlatform() == Common::kPlatformApple2GS) {
434 		_opCodes[176].parameters = "n";  // hide.mouse
435 		_opCodes[178].parameters = "n";  // show.mouse
436 	}
437 
438 	// FIXME: Apply this fix to other games also that use 2 arguments for command 182.
439 	// 'adj.ego.move.to.x.y' (i.e. command 182) takes 2 arguments for at least the
440 	// Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316. Amiga's Gold Rush
441 	// has been set to use AGI 3.149 in ScummVM so that's why this initialization is
442 	// here and not in setupV2Game.
443 	if (getGameID() == GID_GOLDRUSH && getPlatform() == Common::kPlatformAmiga)
444 		_opCodes[182].parameters = "vv";
445 
446 	// add invalid entries for every opcode, that is not defined at all
447 	for (int opCodeNr = opCodesTableSize; opCodeNr < opCodesTableMaxSize; opCodeNr++) {
448 		_opCodes[opCodeNr].name = "illegal";
449 		_opCodes[opCodeNr].parameters = "";
450 		_opCodes[opCodeNr].functionPtr = nullptr;
451 	}
452 
453 	for (int opCodeNr = opCodesCondTableSize; opCodeNr < opCodesCondTableMaxSize; opCodeNr++) {
454 		_opCodesCond[opCodeNr].name = "illegal";
455 		_opCodesCond[opCodeNr].parameters = "";
456 		_opCodesCond[opCodeNr].functionPtr = nullptr;
457 	}
458 
459 	// calculate parameter size
460 	for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
461 		_opCodes[opCodeNr].parameterSize = strlen( _opCodes[opCodeNr].parameters);
462 	}
463 
464 	for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
465 		_opCodesCond[opCodeNr].parameterSize = strlen( _opCodesCond[opCodeNr].parameters);
466 	}
467 }
468 
469 } // End of namespace Agi
470