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 "glk/magnetic/magnetic_defs.h"
24 #include "glk/magnetic/magnetic.h"
25 #include "common/file.h"
26 #include "common/textconsole.h"
27 
28 namespace Glk {
29 namespace Magnetic {
30 
31 const char *const no_hints = "[Hints are not available.]\n";
32 const char *const not_supported = "[This function is not supported.]\n";
33 const char *const undo_ok = "\n[Previous turn undone.]";
34 const char *const undo_fail = "\n[You can't \"undo\" what hasn't been done!]";
35 
36 #define ms_fatal error
37 
38 #if defined(LOGEMU) || defined(LOGGFX) || defined(LOGHNT)
39 FILE *dbg_log;
40 #ifndef LOG_FILE
41 #error LOG_FILE must be defined to be the name of the log file.
42 #endif
43 #endif
44 
45 #ifdef LOGEMU
out(char * format,...)46 void out(char *format, ...) {
47 	va_list a;
48 
49 	va_start(a, format);
50 	vfprintf(dbg_log, format, a);
51 	va_end(a);
52 }
53 #endif
54 #if defined(LOGGFX) || defined(LOGHNT)
out2(char * format,...)55 void out2(char *format, ...) {
56 	va_list a;
57 
58 	va_start(a, format);
59 	vfprintf(dbg_log, format, a);
60 	va_end(a);
61 	fflush(dbg_log);
62 }
63 #endif
64 
65 /* Convert virtual pointer to effective pointer */
effective(type32 ptr)66 type8 *Magnetic::effective(type32 ptr) {
67 	if ((version < 4) && (mem_size == 0x10000))
68 		return &(code[ptr & 0xffff]);
69 	if (ptr >= mem_size) {
70 		ms_fatal("Outside memory experience");
71 		return code;
72 	}
73 
74 	return &(code[ptr]);
75 }
76 
write_l(type8 * ptr,type32 val)77 void Magnetic::write_l(type8 *ptr, type32 val) {
78 	ptr[3] = (type8) val;
79 	val >>= 8;
80 	ptr[2] = (type8) val;
81 	val >>= 8;
82 	ptr[1] = (type8) val;
83 	val >>= 8;
84 	ptr[0] = (type8) val;
85 }
86 
write_w(type8 * ptr,type16 val)87 void Magnetic::write_w(type8 *ptr, type16 val) {
88 	ptr[1] = (type8) val;
89 	val >>= 8;
90 	ptr[0] = (type8) val;
91 }
92 
rand_emu()93 type32 Magnetic::rand_emu() {
94 	rseed = 1103515245L * rseed + 12345L;
95 	return rseed & 0x7fffffffL;
96 }
97 
ms_freemem()98 void Magnetic::ms_freemem() {
99 	if (code)
100 		free(code);
101 	if (string)
102 		free(string);
103 	if (string2)
104 		free(string2);
105 	if (string3)
106 		free(string3);
107 	if (dict)
108 		free(dict);
109 	if (undo[0])
110 		free(undo[0]);
111 	if (undo[1])
112 		free(undo[1]);
113 	if (restart)
114 		free(restart);
115 	code = string = string2 = string3 = dict = undo[0] = undo[1] = restart = 0;
116 	if (gfx_data)
117 		free(gfx_data);
118 	if (gfx_buf)
119 		free(gfx_buf);
120 	if (gfx2_hdr)
121 		free(gfx2_hdr);
122 	if (gfx2_buf)
123 		free(gfx2_buf);
124 	delete gfx_fp;
125 
126 	gfx_data = gfx_buf = gfx2_hdr = gfx2_buf = nullptr;
127 	gfx2_name = 0;
128 	gfx_fp = nullptr;
129 	gfx_ver = 0;
130 	gfxtable = table_dist = 0;
131 #ifndef NO_ANIMATION
132 	pos_table_size = 0;
133 	command_index = 0;
134 	anim_repeat = 0;
135 	pos_table_index = -1;
136 	pos_table_max = -1;
137 #endif
138 	lastchar = 0;
139 	if (hints)
140 		free(hints);
141 	if (hint_contents)
142 		free(hint_contents);
143 	hints = 0;
144 	hint_contents = 0;
145 	if (snd_hdr)
146 		free(snd_hdr);
147 	if (snd_buf)
148 		free(snd_buf);
149 	snd_hdr = nullptr;
150 	snd_hsize = 0;
151 	snd_buf = nullptr;
152 }
153 
init_gfx1(type8 * header)154 type8 Magnetic::init_gfx1(type8 *header) {
155 #ifdef SAVEMEM
156 	type32 i;
157 #endif
158 
159 	if (!(gfx_buf = (type8 *)malloc(MAX_PICTURE_SIZE))) {
160 		delete gfx_fp;
161 		gfx_fp = nullptr;
162 		return 1;
163 	}
164 #ifdef SAVEMEM
165 	if (!(gfx_data = (type8 *)malloc(128))) {
166 #else
167 	size_t dataSize = read_l(header + 4) - 8;
168 	if (!(gfx_data = (type8 *)malloc(dataSize))) {
169 #endif
170 		free(gfx_buf);
171 		delete gfx_fp;
172 		gfx_buf = nullptr;
173 		gfx_fp = nullptr;
174 		return 1;
175 	}
176 #ifdef SAVEMEM
177 	if (!fp.read(gfx_data, 128, 1, gfx_fp)) {
178 #else
179 	if (gfx_fp->read(gfx_data, dataSize) != dataSize) {
180 #endif
181 		free(gfx_data);
182 		free(gfx_buf);
183 		delete gfx_fp;
184 		gfx_data = gfx_buf = nullptr;
185 		gfx_fp = nullptr;
186 		return 1;
187 	}
188 
189 #ifdef SAVEMEM
190 	for (i = 0; i < 128; i += 4)
191 		if (!read_l(gfx_data + i))
192 			write_l(gfx_data + i, read_l(header + 4));
193 #else
194 	delete gfx_fp;
195 	gfx_fp = nullptr;
196 #endif
197 
198 	gfx_ver = 1;
199 	return 2;
200 }
201 
202 type8 Magnetic::init_gfx2(type8 *header) {
203 	if (!(gfx_buf = (type8 *)malloc(MAX_PICTURE_SIZE))) {
204 		delete gfx_fp;
205 		gfx_fp = nullptr;
206 		return 1;
207 	}
208 
209 	gfx2_hsize = read_w(header + 4);
210 	if (!(gfx2_hdr = (type8 *)malloc(gfx2_hsize))) {
211 		free(gfx_buf);
212 		delete gfx_fp;
213 		gfx_buf = nullptr;
214 		gfx_fp = nullptr;
215 		return 1;
216 	}
217 
218 	gfx_fp->seek(6);
219 	if (gfx_fp->read(gfx2_hdr, gfx2_hsize) != gfx2_hsize) {
220 		free(gfx_buf);
221 		free(gfx2_hdr);
222 		delete gfx_fp;
223 		gfx_buf = nullptr;
224 		gfx2_hdr = 0;
225 		gfx_fp = nullptr;
226 		return 1;
227 	}
228 
229 	gfx_ver = 2;
230 	return 2;
231 }
232 
233 type8 Magnetic::init_snd(type8 *header) {
234 	if (!(snd_buf = (type8 *)malloc(MAX_MUSIC_SIZE))) {
235 		delete snd_fp;
236 		snd_fp = nullptr;
237 		return 1;
238 	}
239 
240 	snd_hsize = read_w(header + 4);
241 	if (!(snd_hdr = (type8 *)malloc(snd_hsize))) {
242 		free(snd_buf);
243 		delete snd_fp;
244 		snd_buf = nullptr;
245 		snd_fp = nullptr;
246 		return 1;
247 	}
248 
249 	snd_fp->seek(6);
250 	if (snd_fp->read(snd_hdr, snd_hsize) != snd_hsize) {
251 		free(snd_buf);
252 		free(snd_hdr);
253 		delete snd_fp;
254 		snd_buf = nullptr;
255 		snd_hdr = nullptr;
256 		snd_fp = nullptr;
257 		return 1;
258 	}
259 
260 	return 2;
261 }
262 
263 type8 Magnetic::ms_init(const char *name, const char *gfxname, const char *hntname, const char *sndname) {
264 	Common::File fp;
265 	type8 header[42], header2[8], header3[4];
266 	type32 i, dict_size, string2_size, code_size, dec;
267 
268 #if defined(LOGEMU) || defined(LOGGFX) || defined(LOGHNT)
269 	dbg_log = fopen(LOG_FILE, "wt");
270 #endif
271 	ms_stop();
272 	if (!name) {
273 		if (!restart)
274 			return 0;
275 		else {
276 			memcpy(code, restart, undo_size);
277 			undo_stat[0] = undo_stat[1] = 0;
278 			ms_showpic(0, 0);
279 		}
280 	} else {
281 		undo_stat[0] = undo_stat[1] = 0;
282 
283 		if (!fp.open(name))
284 			return 0;
285 		if ((fp.read(header, 42) != 42) || (read_l(header) != 0x4d615363))
286 			return 0;
287 		if (read_l(header + 8) != 42)
288 			return 0;
289 
290 		ms_freemem();
291 		version = header[13];
292 		code_size = read_l(header + 14);
293 		string_size = read_l(header + 18);
294 		string2_size = read_l(header + 22);
295 		dict_size = read_l(header + 26);
296 		undo_size = read_l(header + 34);
297 		undo_pc = read_l(header + 38);
298 
299 		if ((version < 4) && (code_size < 65536))
300 			mem_size = 65536;
301 		else
302 			mem_size = code_size;
303 
304 		/* Some C libraries don't like malloc(0), so make
305 		   sure that undo_size is always positive. */
306 		if (undo_size == 0)
307 			undo_size = 8;
308 
309 		sd = (type8)((dict_size != 0L) ? 1 : 0); /* if (sd) => separate dict */
310 
311 		if (!(code = (type8 *)malloc(mem_size)) || !(string2 = (type8 *)malloc(string2_size)) ||
312 		        !(restart = (type8 *)malloc(undo_size)) || (sd &&
313 		                !(dict = (type8 *)malloc(dict_size)))) {
314 			ms_freemem();
315 			fp.close();
316 			return 0;
317 		}
318 		if (string_size > MAX_STRING_SIZE) {
319 			if (!(string = (type8 *)malloc(MAX_STRING_SIZE)) ||
320 			        !(string3 = (type8 *)malloc(string_size - MAX_STRING_SIZE))) {
321 				ms_freemem();
322 				fp.close();
323 				return 0;
324 			}
325 		} else {
326 			if (!(string = (type8 *)malloc(string_size))) {
327 				ms_freemem();
328 				fp.close();
329 				return 0;
330 			}
331 		}
332 		if (!(undo[0] = (type8 *)malloc(undo_size)) || !(undo[1] = (type8 *)malloc(undo_size))) {
333 			ms_freemem();
334 			fp.close();
335 			return 0;
336 		}
337 		if (fp.read(code, code_size) != code_size) {
338 			ms_freemem();
339 			fp.close();
340 			return 0;
341 		}
342 		memcpy(restart, code, undo_size);   /* fast restarts */
343 		if (string_size > MAX_STRING_SIZE) {
344 			if (fp.read(string, MAX_STRING_SIZE) != MAX_STRING_SIZE) {
345 				ms_freemem();
346 				fp.close();
347 				return 0;
348 			}
349 			if (fp.read(string3, string_size - MAX_STRING_SIZE) != string_size - MAX_STRING_SIZE) {
350 				ms_freemem();
351 				fp.close();
352 				return 0;
353 			}
354 		} else {
355 			if (fp.read(string, string_size) != string_size) {
356 				ms_freemem();
357 				fp.close();
358 				return 0;
359 			}
360 		}
361 		if (fp.read(string2, string2_size) != string2_size) {
362 			ms_freemem();
363 			fp.close();
364 			return 0;
365 		}
366 		if (sd && fp.read(dict, dict_size) != dict_size)  {
367 			ms_freemem();
368 			fp.close();
369 			return 0;
370 		}
371 		dec = read_l(header + 30);
372 		if (dec >= string_size)
373 			decode_table = string2 + dec - string_size;
374 		else {
375 			if (dec >= MAX_STRING_SIZE)
376 				decode_table = string3 + dec - MAX_STRING_SIZE;
377 			else
378 				decode_table = string + dec;
379 		}
380 		fp.close();
381 	}
382 
383 	for (i = 0; i < 8; i++)
384 		dreg[i] = areg[i] = 0;
385 	write_reg(8 + 7, 2, 0xfffe);    /* Stack-pointer, -2 due to MS-DOS segments */
386 	pc = 0;
387 	zflag = nflag = cflag = vflag = 0;
388 	i_count = 0;
389 	running = 1;
390 
391 	if (!name)
392 		return (type8)(gfx_buf ? 2 : 1);    /* Restarted */
393 
394 	if (version == 4) {
395 		/* Try loading a hint file */
396 		Common::File hnt_fp;
397 		if (hntname && hnt_fp.open(hntname)) {
398 			if ((hnt_fp.read(&header3, 4) == 4) && (read_l(header3) == 0x4D614874)) {
399 				type8 buf[8];
400 				type16 j, blkcnt, elcnt, ntype, elsize, conidx;
401 
402 				/* Allocate memory for hints */
403 				hints = (ms_hint *)malloc(MAX_HINTS * sizeof(struct ms_hint));
404 				hint_contents = (type8 *)malloc(MAX_HCONTENTS);
405 				if ((hints != 0) && (hint_contents != 0)) {
406 					/* Read number of blocks */
407 					if (hnt_fp.read(&buf, 2) != 2 && !hnt_fp.eos())
408 						return 0;
409 					blkcnt = read_w2(buf);
410 #ifdef LOGHNT
411 					out2("Blocks: %d\n", blkcnt);
412 #endif
413 					conidx = 0;
414 					for (i = 0; i < blkcnt; i++) {
415 #ifdef LOGHNT
416 						out2("\nBlock No. %d\n", i);
417 #endif
418 						/* Read number of elements */
419 						if (hnt_fp.read(&buf, 2) != 2 && !hnt_fp.eos()) return 0;
420 						elcnt = read_w2(buf);
421 #ifdef LOGHNT
422 						out2("Elements: %d\n", elcnt);
423 #endif
424 						hints[i].elcount = elcnt;
425 
426 						/* Read node type */
427 						if (hnt_fp.read(&buf, 2) != 2 && !hnt_fp.eos()) return 0;
428 						ntype = read_w2(buf);
429 #ifdef LOGHNT
430 						if (ntype == 1)
431 							out2("Type: Node\n");
432 						else
433 							out2("Type: Leaf\n");
434 #endif
435 						hints[i].nodetype = ntype;
436 						hints[i].content = (const char *)hint_contents + conidx;
437 #ifdef LOGHNT
438 						out2("Elements:\n");
439 #endif
440 						for (j = 0; j < elcnt; j++) {
441 							if (hnt_fp.read(&buf, 2) != 2 && !hnt_fp.eos()) return 0;
442 							elsize = read_w2(buf);
443 							if (hnt_fp.read(hint_contents + conidx, elsize) != elsize && !hnt_fp.eos()) return 0;
444 							hint_contents[conidx + elsize - 1] = '\0';
445 #ifdef LOGHNT
446 							out2("%s\n", hint_contents + conidx);
447 #endif
448 							conidx += elsize;
449 						}
450 
451 						/* Do we need a jump table? */
452 						if (ntype == 1) {
453 #ifdef LOGHNT
454 							out2("Jump to block:\n");
455 #endif
456 							for (j = 0; j < elcnt; j++) {
457 								if (hnt_fp.read(&buf, 2) != 2 && !hnt_fp.eos()) return 0;
458 								hints[i].links[j] = read_w2(buf);
459 #ifdef LOGHNT
460 								out2("%d\n", hints[i].links[j]);
461 #endif
462 							}
463 						}
464 
465 						/* Read the parent block */
466 						if (hnt_fp.read(&buf, 2) != 2 && !hnt_fp.eos()) return 0;
467 						hints[i].parent = read_w2(buf);
468 #ifdef LOGHNT
469 						out2("Parent: %d\n", hints[i].parent);
470 #endif
471 					}
472 				} else {
473 					if (hints)
474 						free(hints);
475 					if (hint_contents)
476 						free(hint_contents);
477 					hints = 0;
478 					hint_contents = 0;
479 				}
480 			}
481 			hnt_fp.close();
482 		}
483 
484 		/* Try loading a music file */
485 		snd_fp = new Common::File();
486 		if (sndname && snd_fp->open(sndname)) {
487 			if (snd_fp->read(&header2, 8) != 8) {
488 				delete snd_fp;
489 				snd_fp = nullptr;
490 			} else {
491 				if (read_l(header2) == 0x4D615364) { /* MaSd */
492 					init_snd(header2);
493 #ifdef LOGSND
494 					out2("Sound file loaded.\n");
495 #endif
496 				}
497 			}
498 		} else {
499 			delete snd_fp;
500 			snd_fp = nullptr;
501 		}
502 	}
503 
504 	if (!gfxname)
505 		return 1;
506 
507 	gfx_fp = new Common::File();
508 	if (!gfx_fp->open(gfxname) || gfx_fp->read(&header2, 8) != 8) {
509 		delete gfx_fp;
510 		gfx_fp = nullptr;
511 		return 1;
512 	}
513 
514 	if (version < 4 && read_l(header2) == 0x4D615069) /* MaPi */
515 		return init_gfx1(header2);
516 	else if (version == 4 && read_l(header2) == 0x4D615032) /* MaP2 */
517 		return init_gfx2(header2);
518 	delete gfx_fp;
519 	gfx_fp = nullptr;
520 	return 1;
521 }
522 
523 type8 Magnetic::is_blank(type16 line, type16 width) {
524 	type32s i;
525 
526 	for (i = line * width; i < (line + 1) * width; i++)
527 		if (gfx_buf[i])
528 			return 0;
529 	return 1;
530 }
531 
532 type8 *Magnetic::ms_extract1(type8 pic, type16 *w, type16 *h, type16 *pal) {
533 	type8 *decodeTable, *data, bit, val, *buf;
534 	type16 tablesize, count;
535 	type32 i, j, upsize, offset;
536 
537 	offset = read_l(gfx_data + 4 * pic);
538 #ifdef SAVEMEM
539 	type32 datasize;
540 
541 	if (fseek(gfx_fp, offset, SEEK_SET) < 0)
542 		return 0;
543 	datasize = read_l(gfx_data + 4 * (pic + 1)) - offset;
544 	if (!(buf = (type8 *)malloc(datasize)))
545 		return 0;
546 	if (fp.read(buf, 1, datasize, gfx_fp) != datasize)
547 		return 0;
548 #else
549 	buf = gfx_data + offset - 8;
550 #endif
551 
552 	for (i = 0; i < 16; i++)
553 		pal[i] = read_w(buf + 0x1c + 2 * i);
554 	w[0] = (type16)(read_w(buf + 4) - read_w(buf + 2));
555 	h[0] = read_w(buf + 6);
556 
557 	tablesize = read_w(buf + 0x3c);
558 	//datasize = read_l(buf + 0x3e);
559 	decodeTable = buf + 0x42;
560 	data = decodeTable + tablesize * 2 + 2;
561 	upsize = h[0] * w[0];
562 
563 	for (i = 0, j = 0, count = 0, val = 0, bit = 7; i < upsize; i++, count--) {
564 		if (!count) {
565 			count = tablesize;
566 			while (count < 0x80) {
567 				if (data[j] & (1 << bit))
568 					count = decodeTable[2 * count];
569 				else
570 					count = decodeTable[2 * count + 1];
571 				if (!bit)
572 					j++;
573 				bit = (type8)(bit ? bit - 1 : 7);
574 			}
575 			count &= 0x7f;
576 			if (count >= 0x10)
577 				count -= 0x10;
578 			else {
579 				val = (type8)count;
580 				count = 1;
581 			}
582 		}
583 		gfx_buf[i] = val;
584 	}
585 	for (j = w[0]; j < upsize; j++)
586 		gfx_buf[j] ^= gfx_buf[j - w[0]];
587 
588 #ifdef SAVEMEM
589 	free(buf);
590 #endif
591 	for (; h[0] > 0 && is_blank((type16)(h[0] - 1), w[0]); h[0]--);
592 	for (i = 0; h[0] > 0 && is_blank((type16)i, w[0]); h[0]--, i++);
593 	return gfx_buf + i * w[0];
594 }
595 
596 type16s Magnetic::find_name_in_header(const char *name, type8 upper) {
597 	type16s header_pos = 0;
598 	char pic_name[8];
599 	type8 i;
600 
601 	for (i = 0; i < 8; i++)
602 		pic_name[i] = 0;
603 	strncpy(pic_name, name, 6);
604 	if (upper) {
605 		for (i = 0; i < 8; i++)
606 			pic_name[i] = (char)toupper(pic_name[i]);
607 	}
608 
609 	while (header_pos < gfx2_hsize) {
610 		const char *hname = (const char *)(gfx2_hdr + header_pos);
611 		if (strncmp(hname, pic_name, 6) == 0)
612 			return header_pos;
613 		header_pos += 16;
614 	}
615 	return -1;
616 }
617 
618 void Magnetic::extract_frame(struct picture *pic) {
619 	type32 i, x, y, bit_x, mask, ywb, yw, value, values[4];
620 
621 	if (pic->width * pic->height > MAX_PICTURE_SIZE) {
622 		ms_fatal("picture too large");
623 		return;
624 	}
625 
626 	for (y = 0; y < pic->height; y++) {
627 		ywb = y * pic->wbytes;
628 		yw = y * pic->width;
629 
630 		for (x = 0; x < pic->width; x++) {
631 			if ((x % 8) == 0) {
632 				for (i = 0; i < 4; i++)
633 					values[i] = pic->data[ywb + (x / 8) + (pic->plane_step * i)];
634 			}
635 
636 			bit_x = 7 - (x & 7);
637 			mask = 1 << bit_x;
638 			value = ((values[0] & mask) >> bit_x) << 0 |
639 			        ((values[1] & mask) >> bit_x) << 1 |
640 			        ((values[2] & mask) >> bit_x) << 2 |
641 			        ((values[3] & mask) >> bit_x) << 3;
642 			value &= 15;
643 
644 			gfx_buf[yw + x] = (type8)value;
645 		}
646 	}
647 }
648 
649 type8 *Magnetic::ms_extract2(const char *name, type16 *w, type16 *h, type16 *pal, type8 *is_anim) {
650 	struct picture main_pic;
651 	type32 offset = 0, length = 0, i;
652 	type16s header_pos = -1;
653 #ifndef NO_ANIMATION
654 	type8 *anim_data;
655 	type32 j;
656 #endif
657 
658 	if (is_anim != 0)
659 		*is_anim = 0;
660 	gfx2_name = name;
661 
662 #ifndef NO_ANIMATION
663 	pos_table_size = 0;
664 #endif
665 
666 #ifdef NO_ANIMATION
667 	/* Find the uppercase (no animation) version of the picture first. */
668 	header_pos = find_name_in_header(name, 1);
669 #endif
670 	if (header_pos < 0)
671 		header_pos = find_name_in_header(name, 0);
672 	if (header_pos < 0)
673 		return 0;
674 
675 	offset = read_l(gfx2_hdr + header_pos + 8);
676 	length = read_l(gfx2_hdr + header_pos + 12);
677 
678 	if (offset != 0) {
679 		if (gfx2_buf) {
680 			free(gfx2_buf);
681 			gfx2_buf = nullptr;
682 		}
683 
684 		gfx2_buf = (type8 *)malloc(length);
685 		if (!gfx2_buf)
686 			return 0;
687 
688 		if (!gfx_fp->seek(offset)) {
689 			free(gfx2_buf);
690 			gfx2_buf = nullptr;
691 			return 0;
692 		}
693 
694 		if (gfx_fp->read(gfx2_buf, length) != length) {
695 			free(gfx2_buf);
696 			gfx2_buf = nullptr;
697 			return 0;
698 		}
699 
700 		for (i = 0; i < 16; i++)
701 			pal[i] = read_w2(gfx2_buf + 4 + (2 * i));
702 
703 		main_pic.data = gfx2_buf + 48;
704 		main_pic.data_size = read_l2(gfx2_buf + 38);
705 		main_pic.width = read_w2(gfx2_buf + 42);
706 		main_pic.height = read_w2(gfx2_buf + 44);
707 		main_pic.wbytes = (type16)(main_pic.data_size / main_pic.height);
708 		main_pic.plane_step = (type16)(main_pic.wbytes / 4);
709 		main_pic.mask = (type8 *)0;
710 		extract_frame(&main_pic);
711 
712 		*w = main_pic.width;
713 		*h = main_pic.height;
714 
715 #ifndef NO_ANIMATION
716 		/* Check for an animation */
717 		anim_data = gfx2_buf + 48 + main_pic.data_size;
718 		if ((anim_data[0] != 0xD0) || (anim_data[1] != 0x5E)) {
719 			type8 *current;
720 			type16 frame_count;
721 			type16 value1, value2;
722 
723 			if (is_anim != 0)
724 				*is_anim = 1;
725 
726 			current = anim_data + 6;
727 			frame_count = read_w2(anim_data + 2);
728 			if (frame_count > MAX_ANIMS) {
729 				ms_fatal("animation frame array too short");
730 				return 0;
731 			}
732 
733 			/* Loop through each animation frame */
734 			for (i = 0; i < frame_count; i++) {
735 				anim_frame_table[i].data = current + 10;
736 				anim_frame_table[i].data_size = read_l2(current);
737 				anim_frame_table[i].width = read_w2(current + 4);
738 				anim_frame_table[i].height = read_w2(current + 6);
739 				anim_frame_table[i].wbytes = (type16)(anim_frame_table[i].data_size / anim_frame_table[i].height);
740 				anim_frame_table[i].plane_step = (type16)(anim_frame_table[i].wbytes / 4);
741 				anim_frame_table[i].mask = (type8 *)0;
742 
743 				current += anim_frame_table[i].data_size + 12;
744 				value1 = read_w2(current - 2);
745 				value2 = read_w2(current);
746 
747 				/* Get the mask */
748 				if ((value1 == anim_frame_table[i].width) && (value2 == anim_frame_table[i].height)) {
749 					type16 skip;
750 
751 					anim_frame_table[i].mask = (type8 *)(current + 4);
752 					skip = read_w2(current + 2);
753 					current += skip + 6;
754 				}
755 			}
756 
757 			/* Get the positioning tables */
758 			pos_table_size = read_w2(current - 2);
759 			if (pos_table_size > MAX_POSITIONS) {
760 				ms_fatal("animation position array too short");
761 				return 0;
762 			}
763 
764 #ifdef LOGGFX_EXT
765 			out2("POSITION TABLE DUMP\n");
766 #endif
767 			for (i = 0; i < pos_table_size; i++) {
768 				pos_table_count[i] = read_w2(current + 2);
769 				current += 4;
770 
771 				if (pos_table_count[i] > MAX_ANIMS) {
772 					ms_fatal("animation position array too short");
773 					return 0;
774 				}
775 
776 				for (j = 0; j < pos_table_count[i]; j++) {
777 					pos_table[i][j].x = read_w2(current);
778 					pos_table[i][j].y = read_w2(current + 2);
779 					pos_table[i][j].number = read_w2(current + 4) - 1;
780 					current += 8;
781 #ifdef LOGGFX_EXT
782 					out2("Position entry: Table: %d  Entry: %d  X: %d Y: %d Frame: %d\n",
783 					     i, j, pos_table[i][j].x, pos_table[i][j].y, pos_table[i][j].number);
784 #endif
785 				}
786 			}
787 
788 			/* Get the command sequence table */
789 			//command_count = read_w2(current);
790 			command_table = current + 2;
791 
792 			for (i = 0; i < MAX_POSITIONS; i++) {
793 				anim_table[i].flag = -1;
794 				anim_table[i].count = -1;
795 			}
796 			command_index = 0;
797 			anim_repeat = 0;
798 			pos_table_index = -1;
799 			pos_table_max = -1;
800 		}
801 #endif
802 		return gfx_buf;
803 	}
804 	return 0;
805 }
806 
807 type8 *Magnetic::ms_extract(type32 pic, type16 *w, type16 *h, type16 *pal, type8 *is_anim) {
808 	if (is_anim)
809 		*is_anim = 0;
810 
811 	if (gfx_buf) {
812 		switch (gfx_ver) {
813 		case 1:
814 			return ms_extract1((type8)pic, w, h, pal);
815 		case 2:
816 			return ms_extract2((const char *)(code + pic), w, h, pal, is_anim);
817 		default:
818 			break;
819 		}
820 	}
821 	return 0;
822 }
823 
824 type8 Magnetic::ms_animate(struct ms_position **positions, type16 *count) {
825 #ifndef NO_ANIMATION
826 	type8 got_anim = 0;
827 	type16 i, j, ttable;
828 
829 	if ((gfx_buf == 0) || (gfx2_buf == 0) || (gfx_ver != 2))
830 		return 0;
831 	if ((pos_table_size == 0) || (command_index < 0))
832 		return 0;
833 
834 	*count = 0;
835 	*positions = (struct ms_position *)0;
836 
837 	while (got_anim == 0) {
838 		if (pos_table_max >= 0) {
839 			if (pos_table_index < pos_table_max) {
840 				for (i = 0; i < pos_table_size; i++) {
841 					if (anim_table[i].flag > -1) {
842 						if (*count >= MAX_FRAMES) {
843 							ms_fatal("returned animation array too short");
844 							return 0;
845 						}
846 
847 						pos_array[*count] = pos_table[i][anim_table[i].flag];
848 #ifdef LOGGFX_EXT
849 						out2("Adding frame %d to buffer\n", pos_array[*count].number);
850 #endif
851 						(*count)++;
852 
853 						if (anim_table[i].flag < (pos_table_count[i] - 1))
854 							anim_table[i].flag++;
855 						if (anim_table[i].count > 0)
856 							anim_table[i].count--;
857 						else
858 							anim_table[i].flag = -1;
859 					}
860 				}
861 				if (*count > 0) {
862 					*positions = pos_array;
863 					got_anim = 1;
864 				}
865 				pos_table_index++;
866 			}
867 		}
868 
869 		if (got_anim == 0) {
870 			type8 command = command_table[command_index];
871 			command_index++;
872 
873 			pos_table_max = -1;
874 			pos_table_index = -1;
875 
876 			switch (command) {
877 			case 0x00:
878 				command_index = -1;
879 				return 0;
880 			case 0x01:
881 #ifdef LOGGFX_EXT
882 				out2("Load Frame Table: %d  Start at: %d  Count: %d\n",
883 				     command_table[command_index], command_table[command_index + 1],
884 				     command_table[command_index + 2]);
885 #endif
886 				ttable = command_table[command_index];
887 				command_index++;
888 
889 				if (ttable - 1 >= MAX_POSITIONS) {
890 					ms_fatal("animation table too short");
891 					return 0;
892 				}
893 
894 				anim_table[ttable - 1].flag = (type16s)(command_table[command_index] - 1);
895 				command_index++;
896 				anim_table[ttable - 1].count = (type16s)(command_table[command_index] - 1);
897 				command_index++;
898 
899 				/* Workaround for Wonderland "catter" animation */
900 				if (v4_id == 0) {
901 					if (strcmp(gfx2_name, "catter") == 0) {
902 						if (command_index == 96)
903 							anim_table[ttable - 1].count = 9;
904 						if (command_index == 108)
905 							anim_table[ttable - 1].flag = -1;
906 						if (command_index == 156)
907 							anim_table[ttable - 1].flag = -1;
908 					}
909 				}
910 				break;
911 			case 0x02:
912 #ifdef LOGGFX_EXT
913 				out2("Animate: %d\n", command_table[command_index]);
914 #endif
915 				pos_table_max = command_table[command_index];
916 				pos_table_index = 0;
917 				command_index++;
918 				break;
919 			case 0x03:
920 #ifdef LOGGFX_EXT
921 				out2("Stop/Repeat Param: %d\n", command_table[command_index]);
922 				command_index = -1;
923 				return 0;
924 #else
925 				if (v4_id == 0) {
926 					command_index = -1;
927 					return 0;
928 				} else {
929 					command_index = 0;
930 					anim_repeat = 1;
931 					pos_table_index = -1;
932 					pos_table_max = -1;
933 					for (j = 0; j < MAX_POSITIONS; j++) {
934 						anim_table[j].flag = -1;
935 						anim_table[j].count = -1;
936 					}
937 				}
938 				break;
939 #endif
940 			case 0x04:
941 #ifdef LOGGFX_EXT
942 				out2("Unknown Command: %d Prop1: %d  Prop2: %d WARNING:not parsed\n", command,
943 				     command_table[command_index], command_table[command_index + 1]);
944 #endif
945 				command_index += 3;
946 				return 0;
947 			case 0x05:
948 				ttable = next_table;
949 				command_index++;
950 
951 				anim_table[ttable - 1].flag = 0;
952 				anim_table[ttable - 1].count = command_table[command_index];
953 
954 				pos_table_max = command_table[command_index];
955 				pos_table_index = 0;
956 				command_index++;
957 				command_index++;
958 				next_table++;
959 				break;
960 			default:
961 				ms_fatal("unknown animation command");
962 				command_index = -1;
963 				return 0;
964 			}
965 		}
966 	}
967 #ifdef LOGGFX_EXT
968 	out2("ms_animate() returning %d frames\n", *count);
969 #endif
970 	return got_anim;
971 #else
972 	return 0;
973 #endif
974 }
975 
976 type8 *Magnetic::ms_get_anim_frame(type16s number, type16 *width, type16 *height, type8 **mask) {
977 #ifndef NO_ANIMATION
978 	if (number >= 0) {
979 		extract_frame(anim_frame_table + number);
980 		*width = anim_frame_table[number].width;
981 		*height = anim_frame_table[number].height;
982 		*mask = anim_frame_table[number].mask;
983 		return gfx_buf;
984 	}
985 #endif
986 	return 0;
987 }
988 
989 type8 Magnetic::ms_anim_is_repeating() const {
990 #ifndef NO_ANIMATION
991 	return anim_repeat;
992 #else
993 	return 0;
994 #endif
995 }
996 
997 type16s Magnetic::find_name_in_sndheader(const char *name) {
998 	type16s header_pos = 0;
999 
1000 	while (header_pos < snd_hsize) {
1001 		const char *hname = (const char *)(snd_hdr + header_pos);
1002 		if (strcmp(hname, name) == 0)
1003 			return header_pos;
1004 		header_pos += 18;
1005 	}
1006 
1007 	return -1;
1008 }
1009 
1010 type8 *Magnetic::sound_extract(const char *name, type32 *length, type16 *tempo) {
1011 	type32 offset = 0;
1012 	type16s header_pos = -1;
1013 
1014 	if (header_pos < 0)
1015 		header_pos = find_name_in_sndheader(name);
1016 	if (header_pos < 0)
1017 		return 0;
1018 
1019 	*tempo = read_w(snd_hdr + header_pos + 8);
1020 	offset = read_l(snd_hdr + header_pos + 10);
1021 	*length = read_l(snd_hdr + header_pos + 14);
1022 
1023 	if (offset != 0) {
1024 		if (!snd_buf)
1025 			return 0;
1026 		if (!snd_fp->seek(offset) || snd_fp->read(snd_buf, *length) != *length)
1027 			return 0;
1028 
1029 		return snd_buf;
1030 	}
1031 
1032 	return nullptr;
1033 }
1034 
1035 void Magnetic::save_undo() {
1036 	type8 *tmp, i;
1037 	type32 tmp32;
1038 
1039 	tmp = undo[0];  /* swap buffers */
1040 	undo[0] = undo[1];
1041 	undo[1] = tmp;
1042 
1043 	for (i = 0; i < 18; i++) {
1044 		tmp32 = undo_regs[0][i];
1045 		undo_regs[0][i] = undo_regs[1][i];
1046 		undo_regs[1][i] = tmp32;
1047 	}
1048 
1049 	memcpy(undo[1], code, undo_size);
1050 	for (i = 0; i < 8; i++) {
1051 		undo_regs[1][i] = dreg[i];
1052 		undo_regs[1][8 + i] = areg[i];
1053 	}
1054 	undo_regs[1][16] = i_count;
1055 	undo_regs[1][17] = pc;  /* status flags intentionally omitted */
1056 
1057 	undo_stat[0] = undo_stat[1];
1058 	undo_stat[1] = 1;
1059 }
1060 
1061 type8 Magnetic::ms_undo() {
1062 	type8 i;
1063 
1064 	ms_flush();
1065 	if (!undo_stat[0])
1066 		return 0;
1067 
1068 	undo_stat[0] = undo_stat[1] = 0;
1069 	memcpy(code, undo[0], undo_size);
1070 	for (i = 0; i < 8; i++) {
1071 		dreg[i] = undo_regs[0][i];
1072 		areg[i] = undo_regs[0][8 + i];
1073 	}
1074 	i_count = undo_regs[0][16];
1075 	pc = undo_regs[0][17];  /* status flags intentionally omitted */
1076 	return 1;
1077 }
1078 
1079 #ifdef LOGEMU
1080 void Magnetic::log_status() {
1081 	int j;
1082 
1083 	fprintf(dbg_log, "\nD0:");
1084 	for (j = 0; j < 8; j++)
1085 		fprintf(dbg_log, " %8.8x", read_reg(j, 3));
1086 	fprintf(dbg_log, "\nA0:");
1087 	for (j = 0; j < 8; j++)
1088 		fprintf(dbg_log, " %8.8x", read_reg(8 + j, 3));
1089 	fprintf(dbg_log, "\nPC=%5.5x (%8.8x) ZCNV=%d%d%d%d - %d instructions\n\n",
1090 	        pc, code, zflag & 1, cflag & 1, nflag & 1, vflag & 1, i_count);
1091 }
1092 #endif
1093 
1094 void Magnetic::ms_status() {
1095 	int j;
1096 
1097 	Common::String s = "D0:";
1098 	for (j = 0; j < 8; j++)
1099 		s += Common::String::format(" %8.8lx", (long) read_reg(j, 3));
1100 	s += "\nA0:";
1101 
1102 	for (j = 0; j < 8; j++)
1103 		s += Common::String::format(" %8.8lx", (long) read_reg(8 + j, 3));
1104 	s += Common::String::format("\nPC=%5.5lx ZCNV=%d%d%d%d - %ld instructions\n",
1105 	                            (long) pc, zflag & 1, cflag & 1, nflag & 1, vflag & 1, (long) i_count);
1106 	warning("%s", s.c_str());
1107 }
1108 
1109 type8 *Magnetic::reg_align(type8 *ptr, type8 size) {
1110 	if (size == 1)
1111 		ptr += 2;
1112 	if (size == 0)
1113 		ptr += 3;
1114 	return ptr;
1115 }
1116 
1117 type32 Magnetic::read_reg(int i, int s) {
1118 	type8 *ptr;
1119 
1120 	if (i > 15) {
1121 		ms_fatal("invalid register in read_reg");
1122 		return 0;
1123 	}
1124 	if (i < 8)
1125 		ptr = (type8 *) & dreg[i];
1126 	else
1127 		ptr = (type8 *) & areg[i - 8];
1128 
1129 	switch (s) {
1130 	case 0:
1131 		return reg_align(ptr, 0)[0];
1132 	case 1:
1133 		return read_w(reg_align(ptr, 1));
1134 	default:
1135 		return read_l(ptr);
1136 	}
1137 }
1138 
1139 void Magnetic::write_reg(int i, int s, type32 val) {
1140 	type8 *ptr;
1141 
1142 	if (i > 15) {
1143 		ms_fatal("invalid register in write_reg");
1144 		return;
1145 	}
1146 	if (i < 8)
1147 		ptr = (type8 *) & dreg[i];
1148 	else
1149 		ptr = (type8 *) & areg[i - 8];
1150 
1151 	switch (s) {
1152 	case 0:
1153 		reg_align(ptr, 0)[0] = (type8)val;
1154 		break;
1155 	case 1:
1156 		write_w(reg_align(ptr, 1), (type16)val);
1157 		break;
1158 	default:
1159 		write_l(ptr, val);
1160 		break;
1161 	}
1162 }
1163 
1164 void Magnetic::char_out(type8 c) {
1165 	static type8 big = 0, period = 0, pipe = 0;
1166 
1167 	if (c == 0xff) {
1168 		big = 1;
1169 		return;
1170 	}
1171 	c &= 0x7f;
1172 	if (read_reg(3, 0)) {
1173 		if (c == 0x5f || c == 0x40)
1174 			c = 0x20;
1175 		if ((c >= 'a') && (c <= 'z'))
1176 			c &= 0xdf;
1177 		if (version < 4)
1178 			ms_statuschar(c);
1179 		return;
1180 	}
1181 	if (c == 0x5e)
1182 		c = 0x0a;
1183 	if (c == 0x40) {
1184 		if (read_reg(2, 0))
1185 			return;
1186 		else
1187 			c = 0x73;
1188 	}
1189 	if (version < 3 && c == 0x7e) {
1190 		lastchar = 0x7e;
1191 		c = 0x0a;
1192 	}
1193 	if (((c > 0x40) && (c < 0x5b)) || ((c > 0x60) && (c < 0x7b))) {
1194 		if (big) {
1195 			c &= 0xdf;
1196 			big = 0;
1197 		}
1198 		if (period)
1199 			char_out(0x20);
1200 	}
1201 	period = 0;
1202 	if (version < 4) {
1203 		if ((c == 0x2e) || (c == 0x3f) || (c == 0x21) || (c == 0x0a))
1204 			big = 1;
1205 		else if (c == 0x22)
1206 			big = 0;
1207 	} else {
1208 		if ((c == 0x20) && (lastchar == 0x0a))
1209 			return;
1210 		if ((c == 0x2e) || (c == 0x3f) || (c == 0x21) || (c == 0x0a))
1211 			big = 1;
1212 		else if (c == 0x22)
1213 			big = 0;
1214 	}
1215 	if (((c == 0x20) || (c == 0x0a)) && (c == lastchar))
1216 		return;
1217 	if (version < 3) {
1218 		if (pipe) {
1219 			pipe = 0;
1220 			return;
1221 		}
1222 		if (c == 0x7c) {
1223 			pipe = 1;
1224 			return;
1225 		}
1226 	} else {
1227 		if (c == 0x7e) {
1228 			c = 0x0a;
1229 			if (lastchar != 0x0a)
1230 				char_out(0x0a);
1231 		}
1232 	}
1233 	lastchar = c;
1234 	if (c == 0x5f)
1235 		c = 0x20;
1236 	if ((c == 0x2e) || (c == 0x2c) || (c == 0x3b) || (c == 0x3a) || (c == 0x21) || (c == 0x3f))
1237 		period = 1;
1238 	ms_putchar(c);
1239 }
1240 
1241 void Magnetic::set_info(type8 b) {
1242 	regnr = (type8)(b & 0x07);
1243 	admode = (type8)((b >> 3) & 0x07);
1244 	opsize = (type8)(b >> 6);
1245 }
1246 
1247 void Magnetic::read_word() {
1248 	type8 *epc;
1249 
1250 	epc = effective(pc);
1251 	byte1 = epc[0];
1252 	byte2 = epc[1];
1253 	pc += 2;
1254 }
1255 
1256 void Magnetic::set_arg1() {
1257 	type8 tmp[2], l1c;
1258 
1259 	is_reversible = 1;
1260 	switch (admode) {
1261 	case 0:
1262 		arg1 = reg_align((type8 *) & dreg[regnr], opsize);  /* Dx */
1263 		is_reversible = 0;
1264 #ifdef LOGEMU
1265 		out(" d%.1d", regnr);
1266 #endif
1267 		break;
1268 	case 1:
1269 		arg1 = reg_align((type8 *) & areg[regnr], opsize);  /* Ax */
1270 		is_reversible = 0;
1271 #ifdef LOGEMU
1272 		out(" a%.1d", regnr);
1273 #endif
1274 		break;
1275 	case 2:
1276 		arg1i = read_reg(8 + regnr, 2);     /* (Ax) */
1277 #ifdef LOGEMU
1278 		out(" (a%.1d)", regnr);
1279 #endif
1280 		break;
1281 	case 3:
1282 		arg1i = read_reg(8 + regnr, 2);     /* (Ax)+ */
1283 		write_reg(8 + regnr, 2, read_reg(8 + regnr, 2) + (1 << opsize));
1284 #ifdef LOGEMU
1285 		out(" (a%.1d)+", regnr);
1286 #endif
1287 		break;
1288 	case 4:
1289 		write_reg(8 + regnr, 2, read_reg(8 + regnr, 2) - (1 << opsize));
1290 		arg1i = read_reg(8 + regnr, 2);     /* -(Ax) */
1291 #ifdef LOGEMU
1292 		out(" -(a%.1d)", regnr);
1293 #endif
1294 		break;
1295 	case 5: {
1296 		type16s i = (type16s) read_w(effective(pc));
1297 		arg1i = read_reg(8 + regnr, 2) + i;
1298 		pc += 2;    /* offset.w(Ax) */
1299 #ifdef LOGEMU
1300 		out(" %X(a%.1d)", i, regnr);
1301 #endif
1302 		}
1303 		break;
1304 	default:
1305 		break;
1306 	case 6:
1307 		tmp[0] = byte1;
1308 		tmp[1] = byte2;
1309 		read_word();    /* offset.b(Ax, Dx/Ax) [1d1c] */
1310 #ifdef LOGEMU
1311 		out(" %.2X(a%.1d,", (int) byte2, regnr);
1312 #endif
1313 		arg1i = read_reg(regnr + 8, 2) + (type8s) byte2;
1314 #ifdef LOGEMU
1315 		if ((byte1 >> 4) > 8)
1316 			out("a%.1d", (byte1 >> 4) - 8);
1317 		else
1318 			out("d%.1d", byte1 >> 4);
1319 #endif
1320 		if (byte1 & 0x08) {
1321 #ifdef LOGEMU
1322 			out(".l)");
1323 #endif
1324 			arg1i += (type32s) read_reg((byte1 >> 4), 2);
1325 		} else {
1326 #ifdef LOGEMU
1327 			out(".w)");
1328 #endif
1329 			arg1i += (type16s) read_reg((byte1 >> 4), 1);
1330 		}
1331 		byte1 = tmp[0];
1332 		byte2 = tmp[1];
1333 		break;
1334 	case 7:     /* specials */
1335 		switch (regnr) {
1336 		case 0:
1337 			arg1i = read_w(effective(pc));  /* $xxxx.W */
1338 			pc += 2;
1339 #ifdef LOGEMU
1340 			out(" %.4X.w", arg1i);
1341 #endif
1342 			break;
1343 		case 1:
1344 			arg1i = read_l(effective(pc));  /* $xxxx */
1345 			pc += 4;
1346 #ifdef LOGEMU
1347 			out(" %.4X", arg1i);
1348 #endif
1349 			break;
1350 		case 2:
1351 			arg1i = (type16s) read_w(effective(pc)) + pc;   /* $xxxx(PC) */
1352 			pc += 2;
1353 #ifdef LOGEMU
1354 			out(" %.4X(pc)", arg1i);
1355 #endif
1356 			break;
1357 		case 3:
1358 			l1c = effective(pc)[0];     /* $xx(PC,A/Dx) */
1359 #ifdef LOGEMU
1360 			out(" ???2", arg1i);
1361 #endif
1362 			if (l1c & 0x08)
1363 				arg1i = pc + (type32s) read_reg((l1c >> 4), 2);
1364 			else
1365 				arg1i = pc + (type16s) read_reg((l1c >> 4), 1);
1366 			l1c = effective(pc)[1];
1367 			pc += 2;
1368 			arg1i += (type8s) l1c;
1369 			break;
1370 		case 4:
1371 			arg1i = pc; /* #$xxxx */
1372 			if (opsize == 0)
1373 				arg1i += 1;
1374 			pc += 2;
1375 			if (opsize == 2)
1376 				pc += 2;
1377 #ifdef LOGEMU
1378 			out(" #%.4X", arg1i);
1379 #endif
1380 			break;
1381 		default:
1382 			break;
1383 		}
1384 		break;
1385 	}
1386 	if (is_reversible)
1387 		arg1 = effective(arg1i);
1388 }
1389 
1390 void Magnetic::set_arg2_nosize(int use_dx, type8 b) {
1391 	if (use_dx)
1392 		arg2 = (type8 *) dreg;
1393 	else
1394 		arg2 = (type8 *) areg;
1395 	arg2 += (b & 0x0e) << 1;
1396 }
1397 
1398 void Magnetic::set_arg2(int use_dx, type8 b) {
1399 	set_arg2_nosize(use_dx, b);
1400 	arg2 = reg_align(arg2, opsize);
1401 }
1402 
1403 void Magnetic::swap_args() {
1404 	type8 *tmp;
1405 
1406 	tmp = arg1;
1407 	arg1 = arg2;
1408 	arg2 = tmp;
1409 }
1410 
1411 void Magnetic::push(type32 c) {
1412 	write_reg(15, 2, read_reg(15, 2) - 4);
1413 	write_l(effective(read_reg(15, 2)), c);
1414 }
1415 
1416 type32 Magnetic::pop() {
1417 	type32 c;
1418 
1419 	c = read_l(effective(read_reg(15, 2)));
1420 	write_reg(15, 2, read_reg(15, 2) + 4);
1421 	return c;
1422 }
1423 
1424 void Magnetic::get_arg() {
1425 #ifdef LOGEMU
1426 	out(" %.4X", pc);
1427 #endif
1428 	set_info(byte2);
1429 	arg2 = effective(pc);
1430 	pc += 2;
1431 	if (opsize == 2)
1432 		pc += 2;
1433 	if (opsize == 0)
1434 		arg2 += 1;
1435 	set_arg1();
1436 }
1437 
1438 void Magnetic::set_flags() {
1439 	type16 i;
1440 	type32 j;
1441 
1442 	zflag = nflag = 0;
1443 	switch (opsize) {
1444 	case 0:
1445 		if (arg1[0] > 127)
1446 			nflag = 0xff;
1447 		if (arg1[0] == 0)
1448 			zflag = 0xff;
1449 		break;
1450 	case 1:
1451 		i = read_w(arg1);
1452 		if (i == 0)
1453 			zflag = 0xff;
1454 		if ((i >> 15) > 0)
1455 			nflag = 0xff;
1456 		break;
1457 	case 2:
1458 		j = read_l(arg1);
1459 		if (j == 0)
1460 			zflag = 0xff;
1461 		if ((j >> 31) > 0)
1462 			nflag = 0xff;
1463 		break;
1464 	default:
1465 		break;
1466 	}
1467 }
1468 
1469 int Magnetic::condition(type8 b) {
1470 	switch (b & 0x0f) {
1471 	case 0:
1472 		return 0xff;
1473 	case 1:
1474 		return 0x00;
1475 	case 2:
1476 		return (zflag | cflag) ^ 0xff;
1477 	case 3:
1478 		return (zflag | cflag);
1479 	case 4:
1480 		return cflag ^ 0xff;
1481 	case 5:
1482 		return cflag;
1483 	case 6:
1484 		return zflag ^ 0xff;
1485 	case 7:
1486 		return zflag;
1487 	case 8:
1488 		return vflag ^ 0xff;
1489 	case 9:
1490 		return vflag;
1491 	case 10:
1492 	case 12:
1493 		return nflag ^ 0xff;
1494 	case 11:
1495 	case 13:
1496 		return nflag;
1497 	case 14:
1498 		return (zflag | nflag) ^ 0xff;
1499 	case 15:
1500 		return (zflag | nflag);
1501 	default:
1502 		break;
1503 	}
1504 	return 0x00;
1505 }
1506 
1507 void Magnetic::branch(type8 b) {
1508 	if (b == 0)
1509 		pc += (type16s) read_w(effective(pc));
1510 	else
1511 		pc += (type8s) b;
1512 #ifdef LOGEMU
1513 	out(" %.4X", pc);
1514 #endif
1515 }
1516 
1517 void Magnetic::do_add(type8 adda) {
1518 	if (adda) {
1519 		if (opsize == 0)
1520 			write_l(arg1, read_l(arg1) + (type8s) arg2[0]);
1521 		if (opsize == 1)
1522 			write_l(arg1, read_l(arg1) + (type16s) read_w(arg2));
1523 		if (opsize == 2)
1524 			write_l(arg1, read_l(arg1) + (type32s) read_l(arg2));
1525 	} else {
1526 		cflag = 0;
1527 		if (opsize == 0) {
1528 			arg1[0] += arg2[0];
1529 			if (arg2[0] > arg1[0])
1530 				cflag = 0xff;
1531 		}
1532 		if (opsize == 1) {
1533 			write_w(arg1, (type16)(read_w(arg1) + read_w(arg2)));
1534 			if (read_w(arg2) > read_w(arg1))
1535 				cflag = 0xff;
1536 		}
1537 		if (opsize == 2) {
1538 			write_l(arg1, read_l(arg1) + read_l(arg2));
1539 			if (read_l(arg2) > read_l(arg1))
1540 				cflag = 0xff;
1541 		}
1542 		if (version < 3 || !quick_flag) {
1543 			/* Corruption onwards */
1544 			vflag = 0;
1545 			set_flags();
1546 		}
1547 	}
1548 }
1549 
1550 void Magnetic::do_sub(type8 suba) {
1551 	if (suba) {
1552 		if (opsize == 0)
1553 			write_l(arg1, read_l(arg1) - (type8s) arg2[0]);
1554 		if (opsize == 1)
1555 			write_l(arg1, read_l(arg1) - (type16s) read_w(arg2));
1556 		if (opsize == 2)
1557 			write_l(arg1, read_l(arg1) - (type32s) read_l(arg2));
1558 	} else {
1559 		cflag = 0;
1560 		if (opsize == 0) {
1561 			if (arg2[0] > arg1[0])
1562 				cflag = 0xff;
1563 			arg1[0] -= arg2[0];
1564 		}
1565 		if (opsize == 1) {
1566 			if (read_w(arg2) > read_w(arg1))
1567 				cflag = 0xff;
1568 			write_w(arg1, (type16)(read_w(arg1) - read_w(arg2)));
1569 		}
1570 		if (opsize == 2) {
1571 			if (read_l(arg2) > read_l(arg1))
1572 				cflag = 0xff;
1573 			write_l(arg1, read_l(arg1) - read_l(arg2));
1574 		}
1575 		if (version < 3 || !quick_flag) {
1576 			/* Corruption onwards */
1577 			vflag = 0;
1578 			set_flags();
1579 		}
1580 	}
1581 }
1582 
1583 void Magnetic::do_eor() {
1584 	if (opsize == 0)
1585 		arg1[0] ^= arg2[0];
1586 	if (opsize == 1)
1587 		write_w(arg1, (type16)(read_w(arg1) ^ read_w(arg2)));
1588 	if (opsize == 2)
1589 		write_l(arg1, read_l(arg1) ^ read_l(arg2));
1590 	cflag = vflag = 0;
1591 	set_flags();
1592 }
1593 
1594 void Magnetic::do_and() {
1595 	if (opsize == 0)
1596 		arg1[0] &= arg2[0];
1597 	if (opsize == 1)
1598 		write_w(arg1, (type16)(read_w(arg1) & read_w(arg2)));
1599 	if (opsize == 2)
1600 		write_l(arg1, read_l(arg1) & read_l(arg2));
1601 	cflag = vflag = 0;
1602 	set_flags();
1603 }
1604 
1605 void Magnetic::do_or() {
1606 	if (opsize == 0)
1607 		arg1[0] |= arg2[0];
1608 	if (opsize == 1)
1609 		write_w(arg1, (type16)(read_w(arg1) | read_w(arg2)));
1610 	if (opsize == 2)
1611 		write_l(arg1, read_l(arg1) | read_l(arg2));
1612 	cflag = vflag = 0;
1613 	set_flags();    /* [1c2b] */
1614 }
1615 
1616 void Magnetic::do_cmp() {
1617 	type8 *tmp;
1618 
1619 	tmp = arg1;
1620 	tmparg[0] = arg1[0];
1621 	tmparg[1] = arg1[1];
1622 	tmparg[2] = arg1[2];
1623 	tmparg[3] = arg1[3];
1624 	arg1 = tmparg;
1625 	quick_flag = 0;
1626 	do_sub(0);
1627 	arg1 = tmp;
1628 }
1629 
1630 void Magnetic::do_move() {
1631 
1632 	if (opsize == 0)
1633 		arg1[0] = arg2[0];
1634 	if (opsize == 1)
1635 		write_w(arg1, read_w(arg2));
1636 	if (opsize == 2)
1637 		write_l(arg1, read_l(arg2));
1638 	if (version < 2 || admode != 1) {
1639 		/* Jinxter: no flags if destination Ax */
1640 		cflag = vflag = 0;
1641 		set_flags();
1642 	}
1643 }
1644 
1645 type8 Magnetic::do_btst(type8 a) {
1646 	a &= admode ? 0x7 : 0x1f;
1647 	while (admode == 0 && a >= 8) {
1648 		a -= 8;
1649 		arg1 -= 1;
1650 	}
1651 	zflag = 0;
1652 	if ((arg1[0] & (1 << a)) == 0)
1653 		zflag = 0xff;
1654 	return a;
1655 }
1656 
1657 void Magnetic::do_bop(type8 b, type8 a) {
1658 #ifdef LOGEMU
1659 	out("bop (%.2x,%.2x) ", (int) b, (int) a);
1660 #endif
1661 	b = b & 0xc0;
1662 	a = do_btst(a);
1663 #ifdef LOGEMU
1664 	if (b == 0x00)
1665 		out("no bop???");
1666 #endif
1667 	if (b == 0x40) {
1668 		arg1[0] ^= (1 << a);    /* bchg */
1669 #ifdef LOGEMU
1670 		out("bchg");
1671 #endif
1672 	}
1673 	if (b == 0x80) {
1674 		arg1[0] &= ((1 << a) ^ 0xff);   /* bclr */
1675 #ifdef LOGEMU
1676 		out("bclr");
1677 #endif
1678 	}
1679 	if (b == 0xc0) {
1680 		arg1[0] |= (1 << a);    /* bset */
1681 #ifdef LOGEMU
1682 		out("bset");
1683 #endif
1684 	}
1685 }
1686 
1687 void Magnetic::check_btst() {
1688 #ifdef LOGEMU
1689 	out("btst");
1690 #endif
1691 	set_info((type8)(byte2 & 0x3f));
1692 	set_arg1();
1693 	set_arg2(1, byte1);
1694 	do_bop(byte2, arg2[0]);
1695 }
1696 
1697 void Magnetic::check_lea() {
1698 #ifdef LOGEMU
1699 	out("lea");
1700 #endif
1701 	if ((byte2 & 0xc0) == 0xc0) {
1702 		set_info(byte2);
1703 		opsize = 2;
1704 		set_arg1();
1705 		set_arg2(0, byte1);
1706 		write_w(arg2, 0);
1707 		if (is_reversible)
1708 			write_l(arg2, arg1i);
1709 		else
1710 			ms_fatal("illegal addressing mode for LEA");
1711 	} else {
1712 		ms_fatal("unimplemented instruction CHK");
1713 	}
1714 }
1715 
1716 void Magnetic::check_movem() {
1717 	type8 l1c;
1718 
1719 #ifdef LOGEMU
1720 	out("movem");
1721 #endif
1722 	set_info((type8)(byte2 - 0x40));
1723 	read_word();
1724 	for (l1c = 0; l1c < 8; l1c++) {
1725 		if (byte2 & 1 << l1c) {
1726 			set_arg1();
1727 			if (opsize == 2)
1728 				write_l(arg1, read_reg(15 - l1c, 2));
1729 			if (opsize == 1)
1730 				write_w(arg1, (type16)read_reg(15 - l1c, 1));
1731 		}
1732 	}
1733 	for (l1c = 0; l1c < 8; l1c++) {
1734 		if (byte1 & 1 << l1c) {
1735 			set_arg1();
1736 			if (opsize == 2)
1737 				write_l(arg1, read_reg(7 - l1c, 2));
1738 			if (opsize == 1)
1739 				write_w(arg1, (type16)read_reg(7 - l1c, 1));
1740 		}
1741 	}
1742 }
1743 
1744 void Magnetic::check_movem2() {
1745 	type8 l1c;
1746 
1747 #ifdef LOGEMU
1748 	out("movem (2)");
1749 #endif
1750 	set_info((type8)(byte2 - 0x40));
1751 	read_word();
1752 	for (l1c = 0; l1c < 8; l1c++) {
1753 		if (byte2 & 1 << l1c) {
1754 			set_arg1();
1755 			if (opsize == 2)
1756 				write_reg(l1c, 2, read_l(arg1));
1757 			if (opsize == 1)
1758 				write_reg(l1c, 1, read_w(arg1));
1759 		}
1760 	}
1761 	for (l1c = 0; l1c < 8; l1c++) {
1762 		if (byte1 & 1 << l1c) {
1763 			set_arg1();
1764 			if (opsize == 2)
1765 				write_reg(8 + l1c, 2, read_l(arg1));
1766 			if (opsize == 1)
1767 				write_reg(8 + l1c, 1, read_w(arg1));
1768 		}
1769 	}
1770 }
1771 
1772 void Magnetic::dict_lookup() {
1773 	type16 dtab, doff, output, output_bak, bank, word, output2;
1774 	type16 tmp16, i, obj_adj, adjlist, adjlist_bak;
1775 	type8 c, c2, c3, flag, matchlen, longest, flag2;
1776 	type8 restartFlag = 0, accept = 0;
1777 
1778 	/*
1779 	   dtab=A5.W                    ;dict_table offset <L22>
1780 	   output=output_bak=A2.W       ;output <L24>
1781 	   A5.W=A6.W                    ;input word
1782 	   doff=A3.W                    ;lookup offset (doff) <L1C>
1783 	   adjlist=A0.W ;adjlist <L1E>
1784 	 */
1785 
1786 	dtab = (type16)read_reg(8 + 5, 1);  /* used by version>0 */
1787 	output = (type16)read_reg(8 + 2, 1);
1788 	write_reg(8 + 5, 1, read_reg(8 + 6, 1));
1789 	doff = (type16)read_reg(8 + 3, 1);
1790 	adjlist = (type16)read_reg(8 + 0, 1);
1791 
1792 	bank = (type16)read_reg(6, 0);  /* l2d */
1793 	flag = 0;       /* l2c */
1794 	word = 0;       /* l26 */
1795 	matchlen = 0;       /* l2e */
1796 	longest = 0;        /* 30e2 */
1797 	write_reg(0, 1, 0); /* apostroph */
1798 
1799 	while ((c = sd ? dict[doff] : effective(doff)[0]) != 0x81) {
1800 		if (c >= 0x80) {
1801 			if (c == 0x82) {
1802 				flag = matchlen = 0;
1803 				word = 0;
1804 				write_reg(8 + 6, 1, read_reg(8 + 5, 1));
1805 				bank++;
1806 				doff++;
1807 				continue;
1808 			}
1809 			c3 = c;
1810 			c &= 0x5f;
1811 			c2 = effective(read_reg(8 + 6, 1))[0] & 0x5f;
1812 			if (c2 == c) {
1813 				write_reg(8 + 6, 1, read_reg(8 + 6, 1) + 1);
1814 				c = effective(read_reg(8 + 6, 1))[0];
1815 				if ((!c) || (c == 0x20) || (c == 0x27) || (!version && (matchlen > 6))) {
1816 					if (c == 0x27) {
1817 						write_reg(8 + 6, 1, read_reg(8 + 6, 1) + 1);
1818 						write_reg(0, 1, 0x200 + effective(read_reg(8 + 6, 1))[0]);
1819 					}
1820 					if ((version < 4) || (c3 != 0xa0))
1821 						accept = 1;
1822 				} else
1823 					restartFlag = 1;
1824 			} else if (!version && matchlen > 6 && !c2)
1825 				accept = 1;
1826 			else
1827 				restartFlag = 1;
1828 		} else {
1829 			c &= 0x5f;
1830 			c2 = effective(read_reg(8 + 6, 1))[0] & 0x5f;
1831 			if ((c2 == c && c) || (version && !c2 && (c == 0x5f))) {
1832 				if (version && !c2 && (c == 0x5f))
1833 					flag = 0x80;
1834 				matchlen++;
1835 				write_reg(8 + 6, 1, read_reg(8 + 6, 1) + 1);
1836 				doff++;
1837 			} else if (!version && matchlen > 6 && !c2)
1838 				accept = 1;
1839 			else
1840 				restartFlag = 1;
1841 		}
1842 		if (accept) {
1843 			effective(read_reg(8 + 2, 1))[0] = (version) ? flag : 0;
1844 			effective(read_reg(8 + 2, 1))[1] = (type8)bank;
1845 			write_w(effective(read_reg(8 + 2, 1) + 2), word);
1846 			write_reg(8 + 2, 1, read_reg(8 + 2, 1) + 4);
1847 			if (matchlen >= longest)
1848 				longest = matchlen;
1849 			restartFlag = 1;
1850 			accept = 0;
1851 		}
1852 		if (restartFlag) {
1853 			write_reg(8 + 6, 1, read_reg(8 + 5, 1));
1854 			flag = matchlen = 0;
1855 			word++;
1856 			if (sd)
1857 				while (dict[doff++] < 0x80);
1858 			else
1859 				while (effective(doff++)[0] < 0x80);
1860 			restartFlag = 0;
1861 		}
1862 	}
1863 	write_w(effective(read_reg(8 + 2, 1)), 0xffff);
1864 
1865 	if (version) {
1866 		/* version > 0 */
1867 		output_bak = output;    /* check synonyms */
1868 		while ((c = effective(output)[1]) != 0xff) {
1869 			if (c == 0x0b) {
1870 				if (sd)
1871 					tmp16 = read_w(&dict[dtab + read_w(effective(output + 2)) * 2]);
1872 				else
1873 					tmp16 = read_w(effective(dtab + read_w(effective(output + 2)) * 2));
1874 				effective(output)[1] = tmp16 & 0x1f;
1875 				write_w(effective(output + 2), (type16)(tmp16 >> 5));
1876 			}
1877 			output += 4;
1878 		}
1879 		output = output_bak;
1880 	}
1881 
1882 	/* l22 = output2,     l1e = adjlist, l20 = obj_adj, l26 = word, l2f = c2 */
1883 	/* l1c = adjlist_bak, 333C = i,      l2d = bank,    l2c = flag, l30e3 = flag2 */
1884 
1885 	write_reg(1, 1, 0); /* D1.W=0  [32B5] */
1886 	flag2 = 0;
1887 	output_bak = output;
1888 	output2 = output;
1889 	while ((bank = effective(output2)[1]) != 0xff) {
1890 		obj_adj = (type16)read_reg(8 + 1, 1);   /* A1.W - obj_adj, ie. adjs for this word */
1891 		write_reg(1, 0, 0); /* D1.B=0 */
1892 		flag = effective(output2)[0];   /* flag */
1893 		word = read_w(effective(output2 + 2));  /* wordnumber */
1894 		output2 += 4;   /* next match */
1895 		if ((read_w(effective(obj_adj))) && (bank == 6)) {
1896 			/* Any adjectives? */
1897 			if ((i = word) != 0) {
1898 				/* Find list of valid adjs */
1899 				do {
1900 					while (effective(adjlist++)[0]);
1901 				} while (--i > 0);
1902 			}
1903 			adjlist_bak = adjlist;
1904 			do {
1905 				adjlist = adjlist_bak;
1906 				c2 = effective(obj_adj)[1]; /* given adjective */
1907 				if ((tmp16 = read_w(effective(obj_adj))) != 0) {
1908 					obj_adj += 2;
1909 					while ((c = effective(adjlist++)[0]) && (c - 3 != c2));
1910 					if (c - 3 != c2)
1911 						write_reg(1, 0, 1); /* invalid adjective */
1912 				}
1913 			} while (tmp16 && !read_reg(1, 0));
1914 			adjlist = (type16)read_reg(8 + 0, 1);
1915 		}
1916 		if (!read_reg(1, 0)) {
1917 			/* invalid_flag */
1918 			flag2 |= flag;
1919 			effective(output)[0] = flag2;
1920 			effective(output)[1] = (type8)bank;
1921 			write_w(effective(output + 2), word);
1922 			output += 4;
1923 		}
1924 	}
1925 	write_reg(8 + 2, 1, output);
1926 	output = output_bak;
1927 
1928 	if (flag2 & 0x80) {
1929 		tmp16 = output;
1930 		output -= 4;
1931 		do {
1932 			output += 4;
1933 			c = effective(output)[0];
1934 		} while (!(c & 0x80));
1935 		write_l(effective(tmp16), read_l(effective(output)) & 0x7fffffff);
1936 		write_reg(8 + 2, 2, tmp16 + 4);
1937 		if (longest > 1) {
1938 			write_reg(8 + 5, 1, read_reg(8 + 5, 1) + longest - 2);
1939 		}
1940 	}
1941 	write_reg(8 + 6, 1, read_reg(8 + 5, 1) + 1);
1942 }
1943 
1944 void Magnetic::do_findprop() {
1945 	type16 tmp;
1946 
1947 	if ((version > 2) && ((read_reg(0, 1) & 0x3fff) > fp_size)) {
1948 		tmp = (type16)(((fp_size - (read_reg(0, 1) & 0x3fff)) ^ 0xffff) << 1);
1949 		tmp += fp_tab;
1950 		tmp = read_w(effective(tmp));
1951 	} else {
1952 		if (version < 2)
1953 			write_reg(0, 2, read_reg(0, 2) & 0x7fff);
1954 		else
1955 			write_reg(0, 1, read_reg(0, 1) & 0x7fff);
1956 		tmp = (type16)read_reg(0, 1);
1957 	}
1958 	tmp &= 0x3fff;
1959 	write_reg(8 + 0, 2, tmp * 14 + properties);
1960 }
1961 
1962 void Magnetic::write_string() {
1963 	static type32 offset_bak;
1964 	static type8 mask_bak;
1965 	type8 c, b, mask;
1966 	type16 ptr;
1967 	type32 offset;
1968 
1969 	if (!cflag) {
1970 		/* new string */
1971 		ptr = (type16)read_reg(0, 1);
1972 		if (!ptr)
1973 			offset = 0;
1974 		else {
1975 			offset = read_w(&decode_table[0x100 + 2 * ptr]);
1976 			if (read_w(&decode_table[0x100])) {
1977 				if (ptr >= read_w(&decode_table[0x100]))
1978 					offset += string_size;
1979 			}
1980 		}
1981 		mask = 1;
1982 	} else {
1983 		offset = offset_bak;
1984 		mask = mask_bak;
1985 	}
1986 	do {
1987 		c = 0;
1988 		while (c < 0x80) {
1989 			if (offset >= string_size)
1990 				b = string2[offset - string_size];
1991 			else {
1992 				if (offset >= MAX_STRING_SIZE)
1993 					b = string3[offset - MAX_STRING_SIZE];
1994 				else
1995 					b = string[offset];
1996 			}
1997 			if (b & mask)
1998 				c = decode_table[0x80 + c];
1999 			else
2000 				c = decode_table[c];
2001 			mask <<= 1;
2002 			if (!mask) {
2003 				mask = 1;
2004 				offset++;
2005 			}
2006 		}
2007 		c &= 0x7f;
2008 		if (c && ((c != 0x40) || (lastchar != 0x20)))
2009 			char_out(c);
2010 	} while (c && ((c != 0x40) || (lastchar != 0x20)));
2011 	cflag = c ? 0xff : 0;
2012 	if (c) {
2013 		offset_bak = offset;
2014 		mask_bak = mask;
2015 	}
2016 }
2017 
2018 void Magnetic::output_number(type16 number) {
2019 	type16 tens = number / 10;
2020 
2021 	if (tens > 0)
2022 		ms_putchar('0' + tens);
2023 	number -= (tens * 10);
2024 	ms_putchar('0' + number);
2025 }
2026 
2027 type16 Magnetic::output_text(const char *text) {
2028 	type16 i;
2029 
2030 	for (i = 0; text[i] != 0; i++)
2031 		ms_putchar(text[i]);
2032 	return i;
2033 }
2034 
2035 type16s Magnetic::hint_input() {
2036 	type8 c1, c2, c3;
2037 
2038 	output_text(">>");
2039 	ms_flush();
2040 
2041 	do {
2042 		c1 = ms_getchar(0);
2043 	} while (c1 == '\n');
2044 	if (c1 == 1)
2045 		return -1; /* New game loaded, abort hints */
2046 
2047 	c2 = ms_getchar(0);
2048 	if (c2 == 1)
2049 		return -1;
2050 
2051 	/* Get and discard any remaining characters */
2052 	c3 = c2;
2053 	while (c3 != '\n') {
2054 		c3 = ms_getchar(0);
2055 		if (c3 == 1)
2056 			return -1;
2057 	}
2058 	ms_putchar('\n');
2059 
2060 	if ((c1 >= '0') && (c1 <= '9')) {
2061 		type16 number = c1 - '0';
2062 		if ((c2 >= '0') && (c2 <= '9')) {
2063 			number *= 10;
2064 			number += c2 - '0';
2065 		}
2066 		return number;
2067 	}
2068 
2069 	if ((c1 >= 'A') && (c1 <= 'Z'))
2070 		c1 = 'a' + (c1 - 'A');
2071 	if ((c1 >= 'a') && (c1 <= 'z')) {
2072 		switch (c1) {
2073 		case 'e':
2074 			return -2; /* End hints */
2075 		case 'n':
2076 			return -3; /* Next hint */
2077 		case 'p':
2078 			return -4; /* Show parent hint list */
2079 		default:
2080 			break;
2081 		}
2082 	}
2083 	return 0;
2084 }
2085 
2086 type16 Magnetic::show_hints_text(ms_hint *hintsData, type16 index) {
2087 	type16 i = 0, j = 0;
2088 	type16s input;
2089 	ms_hint *hint = hintsData + index;
2090 
2091 	while (1) {
2092 		switch (hint->nodetype) {
2093 
2094 		case 1: /* folders */
2095 			output_text("Hint categories:\n");
2096 			for (i = 0, j = 0; i < hint->elcount; i++) {
2097 				output_number(i + 1);
2098 				output_text(". ");
2099 				j += output_text(hint->content + j) + 1;
2100 				ms_putchar('\n');
2101 			}
2102 			output_text("Enter hint category number, ");
2103 			if (hint->parent != 0xffff)
2104 				output_text("P for the parent hint menu, ");
2105 			output_text("or E to end hintsData.\n");
2106 
2107 			input = hint_input();
2108 			switch (input) {
2109 			case -1: /* A new game is being loaded */
2110 				return 1;
2111 			case -2: /* End hintsData */
2112 				return 1;
2113 			case -4: /* Show parent hint list */
2114 				if (hint->parent != 0xffff)
2115 					return 0;
2116 				// fallthrough
2117 			default:
2118 				if ((input > 0) && (input <= hint->elcount)) {
2119 					if (show_hints_text(hintsData, hint->links[input - 1]) == 1)
2120 						return 1;
2121 				}
2122 				break;
2123 			}
2124 			break;
2125 
2126 		case 2: /* hintsData */
2127 			if (i < hint->elcount) {
2128 				output_number(i + 1);
2129 				output_text(". ");
2130 				j += output_text(hint->content + j) + 1;
2131 
2132 				if (i == hint->elcount - 1) {
2133 					output_text("\nNo more hintsData.\n");
2134 					return 0; /* Last hint */
2135 				} else {
2136 					output_text("\nEnter N for the next hint, ");
2137 					output_text("P for the parent hint menu, ");
2138 					output_text("or E to end hintsData.\n");
2139 				}
2140 
2141 				input = hint_input();
2142 				switch (input) {
2143 				case -1: /* A new game is being loaded */
2144 					return 1;
2145 				case -2: /* End hintsData */
2146 					return 1;
2147 				case -3:
2148 					i++;
2149 					break;
2150 				case -4: /* Show parent hint list */
2151 					return 0;
2152 				default:
2153 					break;
2154 				}
2155 			} else
2156 				return 0;
2157 			break;
2158 
2159 		default:
2160 			break;
2161 		}
2162 	}
2163 	return 0;
2164 }
2165 
2166 void Magnetic::do_line_a() {
2167 	type8 l1c;
2168 	char *str;
2169 	type16 ptr, ptr2, tmp16, dtype;
2170 	type32 a1reg, tmp32;
2171 
2172 #ifdef LOGGFX
2173 	/*
2174 	    if (((byte2-0xdd) == 4) || ((byte2-0xdd) == 13))
2175 	        out2("--> %d\n",byte2-0xdd);
2176 	    else
2177 	        out2("LINE A %d\n",byte2-0xdd);
2178 	 */
2179 #endif
2180 	if ((byte2 < 0xdd) || (version < 4 && byte2 < 0xe4) || (version < 2 && byte2 < 0xed)) {
2181 		ms_flush(); /* flush output-buffer */
2182 		rand_emu(); /* Increase game randomness */
2183 		l1c = ms_getchar(1);    /* 0 means UNDO */
2184 		if (l1c == 1)
2185 			return;
2186 		if (l1c)
2187 			write_reg(1, 2, l1c);   /* d1=getkey() */
2188 		else {
2189 			if ((l1c = ms_undo()) != 0)
2190 				output_text(undo_ok);
2191 			else
2192 				output_text(undo_fail);
2193 			if (!l1c)
2194 				write_reg(1, 2, '\n');
2195 		}
2196 	} else
2197 		switch (byte2 - 0xdd) {
2198 
2199 		case 0: /* A0DD - Won't probably be needed at all */
2200 			break;
2201 
2202 		case 1: /* A0DE */
2203 			write_reg(1, 0, 1); /* Should remove the manual check */
2204 			break;
2205 
2206 		case 2: /* A0DF */
2207 			a1reg = (type32)read_reg(9, 2);
2208 			dtype = (code + a1reg + 2)[0];
2209 
2210 			switch (dtype) {
2211 			case 7: /* Picture */
2212 #ifdef LOGGFX
2213 				out2("PICTURE IS %s\n", code + a1reg + 3);
2214 #endif
2215 				/* gfx mode = normal, df is not called if graphics are off */
2216 				ms_showpic(a1reg + 3, 2);
2217 				break;
2218 
2219 			case 10: /* Open window commands */
2220 				switch ((code + a1reg + 3)[0]) {
2221 				case 4: /* Help/Hints */
2222 					if (hints != 0) {
2223 						if (ms_showhints(hints) == 0)
2224 							show_hints_text(hints, 0);
2225 					} else
2226 						output_text(no_hints);
2227 					break;
2228 				case 0: /* Carried items */
2229 				case 1: /* Room items */
2230 				case 2: /* Map */
2231 				case 3: /* Compass */
2232 					output_text(not_supported);
2233 					break;
2234 				default:
2235 					break;
2236 				}
2237 				break;
2238 
2239 			case 13: /* Music */
2240 				switch ((code + a1reg + 3)[0]) {
2241 				case 0: /* stop music */
2242 					ms_playmusic(0, 0, 0);
2243 					break;
2244 				default: /* play music */
2245 #ifdef LOGSND
2246 					out2("MUSIC IS %s\n", code + a1reg + 3);
2247 #endif
2248 					{
2249 						type32 length = 0;
2250 						type16 tempo = 0;
2251 						type8 *midi = sound_extract((const char *)(code + a1reg + 3), &length, &tempo);
2252 						if (midi != NULL)
2253 							ms_playmusic(midi, length, tempo);
2254 					}
2255 					break;
2256 				}
2257 				break;
2258 
2259 			default:
2260 				break;
2261 			}
2262 			break;
2263 
2264 		case 3: /* A0E0 */
2265 			/* printf("A0E0 stubbed\n"); */
2266 			break;
2267 
2268 		case 4: /* A0E1 Read from keyboard to (A1), status in D1 (0 for ok) */
2269 			ms_flush();
2270 			rand_emu();
2271 			tmp32 = read_reg(8 + 1, 2);
2272 			str = (char *)effective(tmp32);
2273 			tmp16 = 0;
2274 			do {
2275 				if (!(l1c = ms_getchar(1))) {
2276 					if (g_vm->shouldQuit())
2277 						return;
2278 					if ((l1c = ms_undo()) != 0)
2279 						output_text(undo_ok);
2280 					else
2281 						output_text(undo_fail);
2282 					if (!l1c) {
2283 						tmp16 = 0;
2284 						str[tmp16++] = '\n';
2285 						l1c = '\n';
2286 						output_text("\n>");
2287 					} else {
2288 						ms_putchar('\n');
2289 						return;
2290 					}
2291 				} else {
2292 					if (l1c == 1)
2293 						return;
2294 					str[tmp16++] = l1c;
2295 #ifdef LOGGFX
2296 					out2("%c", l1c);
2297 #endif
2298 				}
2299 			} while (l1c != '\n' && tmp16 < 256);
2300 			write_reg(8 + 1, 2, tmp32 + tmp16 - 1);
2301 			if (tmp16 != 256 && tmp16 != 1)
2302 				write_reg(1, 1, 0);
2303 			else
2304 				write_reg(1, 1, 1);
2305 			break;
2306 
2307 		case 5: /* A0E2 */
2308 			/* printf("A0E2 stubbed\n"); */
2309 			break;
2310 
2311 		case 6: /* A0E3 */
2312 			if (read_reg(1, 2) == 0) {
2313 				if ((version < 4) || (read_reg(6, 2) == 0))
2314 					ms_showpic(0, 0);
2315 			}
2316 			/* printf("\nMoves: %u\n",read_reg(0,1)); */
2317 			break;
2318 
2319 		case 7: /* A0E4 sp+=4, RTS */
2320 			write_reg(8 + 7, 1, read_reg(8 + 7, 1) + 4);
2321 			pc = pop();
2322 			break;
2323 
2324 		case 8: /* A0E5 set z, RTS */
2325 		case 9: /* A0E6 clear z, RTS */
2326 			pc = pop();
2327 			zflag = (byte2 == 0xe5) ? 0xff : 0;
2328 			break;
2329 
2330 		case 10: /* A0E7 set z */
2331 			zflag = 0xff;
2332 			break;
2333 
2334 		case 11: /* A0E8 clear z */
2335 			zflag = 0;
2336 			break;
2337 
2338 		case 12: /* A0E9 [3083 - j] */
2339 			ptr = (type16)read_reg(8 + 0, 1);
2340 			ptr2 = (type16)read_reg(8 + 1, 1);
2341 			do {
2342 				l1c = dict[ptr2++];
2343 				effective(ptr++)[0] = l1c;
2344 			} while ((l1c & 0x80) == 0);
2345 			write_reg(8 + 0, 1, ptr);
2346 			write_reg(8 + 1, 1, ptr2);
2347 			break;
2348 
2349 		case 13: /* A0EA A1=write_dictword(A1,D1=output_mode) */
2350 			ptr = (type16)read_reg(8 + 1, 1);
2351 			tmp32 = read_reg(3, 0);
2352 			write_reg(3, 0, read_reg(1, 0));
2353 			do {
2354 				l1c = dict[ptr++];
2355 				char_out(l1c);
2356 			} while (l1c < 0x80);
2357 			write_reg(8 + 1, 1, ptr);
2358 			write_reg(3, 0, tmp32);
2359 			break;
2360 
2361 		case 14: /* A0EB [3037 - j] */
2362 			dict[read_reg(8 + 1, 1)] = (type8)read_reg(1, 0);
2363 			break;
2364 
2365 		case 15: /* A0EC */
2366 			write_reg(1, 0, dict[read_reg(8 + 1, 1)]);
2367 			break;
2368 
2369 		case 16:
2370 			ms_stop();  /* infinite loop A0ED */
2371 			break;
2372 		case 17:
2373 			if (!ms_init(nullptr, nullptr, nullptr, nullptr))
2374 				ms_stop();  /* restart game ie. pc, sp etc. A0EE */
2375 			break;
2376 		case 18:    /* printer A0EF */
2377 			break;
2378 		case 19:
2379 			ms_showpic(read_reg(0, 0), (type8)read_reg(1, 0));  /* Do_picture(D0) A0F0 */
2380 			break;
2381 		case 20:
2382 			ptr = (type16)read_reg(8 + 1, 1);   /* A1=nth_string(A1,D0) A0F1 */
2383 			tmp32 = read_reg(0, 1);
2384 			while (tmp32-- > 0) {
2385 				while (effective(ptr++)[0]);
2386 			}
2387 			write_reg(8 + 1, 1, ptr);
2388 			break;
2389 
2390 		case 21: /* [2a43] A0F2 */
2391 			cflag = 0;
2392 			write_reg(0, 1, read_reg(2, 1));
2393 			do_findprop();
2394 			ptr = (type16)read_reg(8 + 0, 1);
2395 			while (read_reg(2, 1) > 0) {
2396 				if (read_w(effective(ptr + 12)) & 0x3fff) {
2397 					cflag = 0xff;
2398 					break;
2399 				}
2400 				if (read_reg(2, 1) == (read_reg(4, 1) & 0x7fff)) {
2401 					cflag = 0xff;
2402 					break;
2403 				}
2404 				ptr -= 0x0e;
2405 				write_reg(2, 1, read_reg(2, 1) - 1);
2406 			}
2407 			break;
2408 
2409 		case 22:
2410 			char_out((type8)read_reg(1, 0));    /* A0F3 */
2411 			break;
2412 
2413 		case 23: /* D7=Save_(filename A0) D1 bytes starting from A1  A0F4 */
2414 			str = (version < 4) ? (char *)effective(read_reg(8 + 0, 1)) : nullptr;
2415 			write_reg(7, 0, ms_save_file(str, effective(read_reg(8 + 1, 1)),
2416 			                             (type16)read_reg(1, 1)));
2417 			break;
2418 
2419 		case 24: /* D7=Load_(filename A0) D1 bytes starting from A1  A0F5 */
2420 			str = (version < 4) ? (char *)effective(read_reg(8 + 0, 1)) : nullptr;
2421 			write_reg(7, 0, ms_load_file(str, effective(read_reg(8 + 1, 1)),
2422 			                             (type16)read_reg(1, 1)));
2423 			break;
2424 
2425 		case 25: /* D1=Random(0..D1-1) [3748] A0F6 */
2426 			l1c = (type8)read_reg(1, 0);
2427 			write_reg(1, 1, rand_emu() % (l1c ? l1c : 1));
2428 			break;
2429 
2430 		case 26: /* D0=Random(0..255) [3742] A0F7 */
2431 			tmp16 = (type16)rand_emu();
2432 			write_reg(0, 0, tmp16 + (tmp16 >> 8));
2433 			break;
2434 
2435 		case 27: /* write string [D0] [2999] A0F8 */
2436 			write_string();
2437 			break;
2438 
2439 		case 28: /* Z,D0=Get_inventory_item(D0) [2a9e] A0F9 */
2440 			zflag = 0;
2441 			ptr = (type16)read_reg(0, 1);
2442 			do {
2443 				write_reg(0, 1, ptr);
2444 				do {
2445 					do_findprop();
2446 					ptr2 = (type16)read_reg(8 + 0, 1);  /* object properties */
2447 					if ((effective(ptr2)[5]) & 1)
2448 						break;  /* is_described or so */
2449 					l1c = effective(ptr2)[6];   /* some_flags */
2450 					tmp16 = read_w(effective(ptr2 + 8));    /* parent_object */
2451 					if (!l1c) {
2452 						/* ordinary object? */
2453 						if (!tmp16)
2454 							zflag = 0xff;   /* return if parent()=player */
2455 						break;  /* otherwise try next */
2456 					}
2457 					if (l1c & 0xcc)
2458 						break;  /* skip worn, bodypart, room, hidden */
2459 					if (tmp16 == 0) {
2460 						/* return if parent()=player? */
2461 						zflag = 0xff;
2462 						break;
2463 					}
2464 					write_reg(0, 1, tmp16); /* else look at parent() */
2465 				} while (1);
2466 				ptr--;
2467 			} while ((!zflag) && ptr);
2468 			write_reg(0, 1, ptr + 1);
2469 			break;
2470 
2471 		case 29: /* [2b18] A0FA */
2472 			ptr = (type16)read_reg(8, 1);
2473 			do {
2474 				if (read_reg(5, 0)) {
2475 					l1c = ((type32)((read_w(effective(ptr)) & 0x3fff)) == read_reg(2, 1));
2476 				} else {
2477 					l1c = (effective(ptr)[0] == read_reg(2, 0));
2478 				}
2479 				if (read_reg(3, 1) == read_reg(4, 1)) {
2480 					cflag = 0;
2481 					write_reg(8, 1, ptr);
2482 				} else {
2483 					write_reg(3, 1, read_reg(3, 1) + 1);
2484 					ptr += 0x0e;
2485 					if (l1c) {
2486 						cflag = 0xff;
2487 						write_reg(8, 1, ptr);
2488 					}
2489 				}
2490 			} while ((!l1c) && (read_reg(3, 1) != read_reg(4, 1)));
2491 			break;
2492 
2493 		case 30: /* [2bd1] A0FB */
2494 			ptr = (type16)read_reg(8 + 1, 1);
2495 			do {
2496 				if (dict)
2497 					while (dict[ptr++] < 0x80);
2498 				else
2499 					while (effective(ptr++)[0] < 0x80);
2500 				write_reg(2, 1, read_reg(2, 1) - 1);
2501 			} while (read_reg(2, 1));
2502 			write_reg(8 + 1, 1, ptr);
2503 			break;
2504 
2505 		case 31: /* [2c3b] A0FC */
2506 			ptr = (type16)read_reg(8 + 0, 1);
2507 			ptr2 = (type16)read_reg(8 + 1, 1);
2508 			do {
2509 				if (dict)
2510 					while (dict[ptr++] < 0x80);
2511 				else
2512 					while (effective(ptr++)[0] < 0x80);
2513 				while (effective(ptr2++)[0]);
2514 				write_reg(0, 1, read_reg(0, 1) - 1);
2515 			} while (read_reg(0, 1));
2516 			write_reg(8 + 0, 1, ptr);
2517 			write_reg(8 + 1, 1, ptr2);
2518 			break;
2519 
2520 		case 32: /* Set properties pointer from A0 [2b7b] A0FD */
2521 			properties = (type16)read_reg(8 + 0, 1);
2522 			if (version > 0)
2523 				fl_sub = (type16)read_reg(8 + 3, 1);
2524 			if (version > 1) {
2525 				fl_tab = (type16)read_reg(8 + 5, 1);
2526 				fl_size = (type16)read_reg(7, 1) + 1;
2527 				/* A3 [routine], A5 [table] and D7 [table-size] */
2528 			}
2529 			if (version > 2) {
2530 				fp_tab = (type16)read_reg(8 + 6, 1);
2531 				fp_size = (type16)read_reg(6, 1);
2532 			}
2533 			break;
2534 
2535 		case 33: /* A0FE */
2536 			do_findprop();
2537 			break;
2538 
2539 		case 34: /* Dictionary_lookup A0FF */
2540 			dict_lookup();
2541 			break;
2542 
2543 		default:
2544 			break;
2545 		}
2546 }
2547 
2548 type8 Magnetic::ms_rungame() {
2549 	type8 l1c;
2550 	type16 ptr;
2551 	type32 tmp32;
2552 #ifdef LOGEMU
2553 	static int stat = 0;
2554 #endif
2555 
2556 	if (!running)
2557 		return running;
2558 	if (pc == undo_pc)
2559 		save_undo();
2560 
2561 #ifdef LOGEMU
2562 	if (pc == 0x0000)
2563 		stat = 0;
2564 	if (stat) {
2565 		log_status();
2566 		fflush(dbg_log);
2567 	}
2568 
2569 	fprintf(dbg_log, "%.8X: ", pc);
2570 #endif
2571 	i_count++;
2572 	read_word();
2573 	switch (byte1 >> 1) {
2574 
2575 	/* 00-0F */
2576 	case 0x00:
2577 		if (byte1 == 0x00) {
2578 			if (byte2 == 0x3c || byte2 == 0x7c) {
2579 				/* OR immediate to CCR (30D9) */
2580 				read_word();
2581 #ifdef LOGEMU
2582 				out("or_ccr #%.2x", byte2);
2583 #endif
2584 				if (byte2 & 0x01)
2585 					cflag = 0xff;
2586 				if (byte2 & 0x02)
2587 					vflag = 0xff;
2588 				if (byte2 & 0x04)
2589 					zflag = 0xff;
2590 				if (byte2 & 0x08)
2591 					nflag = 0xff;
2592 			} else {
2593 				/* OR [27df] */
2594 #ifdef LOGEMU
2595 				out("or");
2596 #endif
2597 				get_arg();
2598 				do_or();
2599 			}
2600 		} else
2601 			check_btst();
2602 		break;
2603 
2604 	case 0x01:
2605 		if (byte1 == 0x02) {
2606 			if (byte2 == 0x3c || byte2 == 0x7c) {
2607 				/* AND immediate to CCR */
2608 				read_word();
2609 #ifdef LOGEMU
2610 				out("and_ccr #%.2x", byte2);
2611 #endif
2612 				if (!(byte2 & 0x01))
2613 					cflag = 0;
2614 				if (!(byte2 & 0x02))
2615 					vflag = 0;
2616 				if (!(byte2 & 0x04))
2617 					zflag = 0;
2618 				if (!(byte2 & 0x08))
2619 					nflag = 0;
2620 			} else {
2621 				/* AND */
2622 #ifdef LOGEMU
2623 				out("and");
2624 #endif
2625 				get_arg();
2626 				do_and();
2627 			}
2628 		} else
2629 			check_btst();
2630 		break;
2631 
2632 	case 0x02:
2633 		if (byte1 == 0x04) {
2634 			/* SUB */
2635 #ifdef LOGEMU
2636 			out("sub");
2637 #endif
2638 			get_arg();
2639 			do_sub(0);
2640 		} else
2641 			check_btst();
2642 		break;
2643 
2644 	case 0x03:
2645 		if (byte1 == 0x06) {
2646 			/* ADD */
2647 #ifdef LOGEMU
2648 			out("addi");
2649 #endif
2650 			get_arg();
2651 			do_add(0);
2652 		} else
2653 			check_btst();
2654 		break;
2655 
2656 	case 0x04:
2657 		if (byte1 == 0x08) {
2658 			/* bit operations (immediate) */
2659 			set_info((type8)(byte2 & 0x3f));
2660 			l1c = (effective(pc))[1];
2661 			pc += 2;
2662 			set_arg1();
2663 			do_bop(byte2, l1c);
2664 		} else
2665 			check_btst();
2666 		break;
2667 
2668 	case 0x05:
2669 		if (byte1 == 0x0a) {
2670 			if (byte2 == 0x3c || byte2 == 0x7c) {
2671 				/* EOR immediate to CCR */
2672 				read_word();
2673 #ifdef LOGEMU
2674 				out("eor_ccr #%.2X", byte2);
2675 #endif
2676 				if (byte2 & 0x01)
2677 					cflag ^= 0xff;
2678 				if (byte2 & 0x02)
2679 					vflag ^= 0xff;
2680 				if (byte2 & 0x04)
2681 					zflag ^= 0xff;
2682 				if (byte2 & 0x08)
2683 					nflag ^= 0xff;
2684 			} else {
2685 				/* EOR */
2686 #ifdef LOGEMU
2687 				out("eor");
2688 #endif
2689 				get_arg();
2690 				do_eor();
2691 			}
2692 		} else
2693 			check_btst();
2694 		break;
2695 
2696 	case 0x06:
2697 		if (byte1 == 0x0c) {
2698 			/* CMP */
2699 #ifdef LOGEMU
2700 			out("cmp");
2701 #endif
2702 			get_arg();
2703 			do_cmp();
2704 		} else
2705 			check_btst();
2706 		break;
2707 
2708 	case 0x07:
2709 		check_btst();
2710 		break;
2711 
2712 	/* 10-1F [3327] MOVE.B */
2713 	case 0x08:
2714 	case 0x09:
2715 	case 0x0a:
2716 	case 0x0b:
2717 	case 0x0c:
2718 	case 0x0d:
2719 	case 0x0e:
2720 	case 0x0f:
2721 
2722 #ifdef LOGEMU
2723 		out("move.b");
2724 #endif
2725 		set_info((type8)(byte2 & 0x3f));
2726 		set_arg1();
2727 		swap_args();
2728 		l1c = (byte1 >> 1 & 0x07) | (byte2 >> 3 & 0x18) | (byte1 << 5 & 0x20);
2729 		set_info(l1c);
2730 		set_arg1();
2731 		do_move();
2732 		break;
2733 
2734 	/* 20-2F [32d1] MOVE.L */
2735 	case 0x10:
2736 	case 0x11:
2737 	case 0x12:
2738 	case 0x13:
2739 	case 0x14:
2740 	case 0x15:
2741 	case 0x16:
2742 	case 0x17:
2743 
2744 #ifdef LOGEMU
2745 		out("move.l");
2746 #endif
2747 		set_info((type8)((byte2 & 0x3f) | 0x80));
2748 		set_arg1();
2749 		swap_args();
2750 		l1c = (byte1 >> 1 & 0x07) | (byte2 >> 3 & 0x18) | (byte1 << 5 & 0x20);
2751 		set_info((type8)(l1c | 0x80));
2752 		set_arg1();
2753 		do_move();
2754 		break;
2755 
2756 	/* 30-3F [3327] MOVE.W */
2757 	case 0x18:
2758 	case 0x19:
2759 	case 0x1a:
2760 	case 0x1b:
2761 	case 0x1c:
2762 	case 0x1d:
2763 	case 0x1e:
2764 	case 0x1f:
2765 
2766 #ifdef LOGEMU
2767 		out("move.w");
2768 #endif
2769 		set_info((type8)((byte2 & 0x3f) | 0x40));
2770 		set_arg1();
2771 		swap_args();
2772 		l1c = (byte1 >> 1 & 0x07) | (byte2 >> 3 & 0x18) | (byte1 << 5 & 0x20);
2773 		set_info((type8)(l1c | 0x40));
2774 		set_arg1();
2775 		do_move();
2776 		break;
2777 
2778 	/* 40-4F various commands */
2779 
2780 	case 0x20:
2781 		if (byte1 == 0x40) {
2782 			/* [31d5] */
2783 			ms_fatal("unimplemented instructions NEGX and MOVE SR,xx");
2784 		} else
2785 			check_lea();
2786 		break;
2787 
2788 	case 0x21:
2789 		if (byte1 == 0x42) {
2790 			/* [3188] */
2791 			if ((byte2 & 0xc0) == 0xc0) {
2792 				ms_fatal("unimplemented instruction MOVE CCR,xx");
2793 			} else {
2794 				/* CLR */
2795 #ifdef LOGEMU
2796 				out("clr");
2797 #endif
2798 				set_info(byte2);
2799 				set_arg1();
2800 				if (opsize == 0)
2801 					arg1[0] = 0;
2802 				if (opsize == 1)
2803 					write_w(arg1, 0);
2804 				if (opsize == 2)
2805 					write_l(arg1, 0);
2806 				nflag = cflag = 0;
2807 				zflag = 0xff;
2808 			}
2809 		} else
2810 			check_lea();
2811 		break;
2812 
2813 	case 0x22:
2814 		if (byte1 == 0x44) {
2815 			/* [31a0] */
2816 			if ((byte2 & 0xc0) == 0xc0) {
2817 				/* MOVE to CCR */
2818 #ifdef LOGEMU
2819 				out("move_ccr");
2820 #endif
2821 				zflag = nflag = cflag = vflag = 0;
2822 				set_info((type8)(byte2 & 0x7f));
2823 				set_arg1();
2824 				byte2 = arg1[1];
2825 				if (byte2 & 0x01)
2826 					cflag = 0xff;
2827 				if (byte2 & 0x02)
2828 					vflag = 0xff;
2829 				if (byte2 & 0x04)
2830 					zflag = 0xff;
2831 				if (byte2 & 0x08)
2832 					nflag = 0xff;
2833 			} else {
2834 #ifdef LOGEMU
2835 				out("neg");
2836 #endif
2837 				set_info(byte2);    /* NEG */
2838 				set_arg1();
2839 				cflag = 0xff;
2840 				if (opsize == 0) {
2841 					arg1[0] = (-arg1[0]);
2842 					cflag = arg1[0] ? 0xff : 0;
2843 				}
2844 				if (opsize == 1) {
2845 					write_w(arg1, (type16)(-1 * read_w(arg1)));
2846 					cflag = read_w(arg1) ? 0xff : 0;
2847 				}
2848 				if (opsize == 2) {
2849 					write_l(arg1, -1 * read_l(arg1));
2850 					cflag = read_l(arg1) ? 0xff : 0;
2851 				}
2852 				vflag = 0;
2853 				set_flags();
2854 			}
2855 		} else
2856 			check_lea();
2857 		break;
2858 
2859 	case 0x23:
2860 		if (byte1 == 0x46) {
2861 			if ((byte2 & 0xc0) == 0xc0) {
2862 				ms_fatal("unimplemented instruction MOVE xx,SR");
2863 			} else {
2864 #ifdef LOGEMU
2865 				out("not");
2866 #endif
2867 				set_info(byte2);    /* NOT */
2868 				set_arg1();
2869 				tmparg[0] = tmparg[1] = tmparg[2] = tmparg[3] = 0xff;
2870 				arg2 = tmparg;
2871 				do_eor();
2872 			}
2873 		} else
2874 			check_lea();
2875 		break;
2876 
2877 	case 0x24:
2878 		if (byte1 == 0x48) {
2879 			if ((byte2 & 0xf8) == 0x40) {
2880 #ifdef LOGEMU
2881 				out("swap");
2882 #endif
2883 				opsize = 2; /* SWAP */
2884 				admode = 0;
2885 				regnr = byte2 & 0x07;
2886 				set_arg1();
2887 				tmp32 = read_w(arg1);
2888 				write_w(arg1, read_w(arg1 + 2));
2889 				write_w(arg1 + 2, (type16)tmp32);
2890 				set_flags();
2891 			} else if ((byte2 & 0xf8) == 0x80) {
2892 #ifdef LOGEMU
2893 				out("ext.w");
2894 #endif
2895 				opsize = 1; /* EXT.W */
2896 				admode = 0;
2897 				regnr = byte2 & 0x07;
2898 				set_arg1();
2899 				if (arg1[1] > 0x7f)
2900 					arg1[0] = 0xff;
2901 				else
2902 					arg1[0] = 0;
2903 				set_flags();
2904 			} else if ((byte2 & 0xf8) == 0xc0) {
2905 #ifdef LOGEMU
2906 				out("ext.l");
2907 #endif
2908 				opsize = 2; /* EXT.L */
2909 				admode = 0;
2910 				regnr = byte2 & 0x07;
2911 				set_arg1();
2912 				if (read_w(arg1 + 2) > 0x7fff)
2913 					write_w(arg1, 0xffff);
2914 				else
2915 					write_w(arg1, 0);
2916 				set_flags();
2917 			} else if ((byte2 & 0xc0) == 0x40) {
2918 #ifdef LOGEMU
2919 				out("pea");
2920 #endif
2921 				set_info((type8)((byte2 & 0x3f) | 0x80));   /* PEA */
2922 				set_arg1();
2923 				if (is_reversible)
2924 					push(arg1i);
2925 				else
2926 					ms_fatal("illegal addressing mode for PEA");
2927 			} else {
2928 				check_movem();  /* MOVEM */
2929 			}
2930 		} else
2931 			check_lea();
2932 		break;
2933 
2934 	case 0x25:
2935 		if (byte1 == 0x4a) {
2936 			/* [3219] TST */
2937 			if ((byte2 & 0xc0) == 0xc0) {
2938 				ms_fatal("unimplemented instruction TAS");
2939 			} else {
2940 #ifdef LOGEMU
2941 				out("tst");
2942 #endif
2943 				set_info(byte2);
2944 				set_arg1();
2945 				cflag = vflag = 0;
2946 				set_flags();
2947 			}
2948 		} else
2949 			check_lea();
2950 		break;
2951 
2952 	case 0x26:
2953 		if (byte1 == 0x4c)
2954 			check_movem2();     /* [3350] MOVEM.L (Ax)+,A/Dx */
2955 		else
2956 			check_lea();    /* LEA */
2957 		break;
2958 
2959 	case 0x27:
2960 		if (byte1 == 0x4e) {
2961 			/* [3290] */
2962 			if (byte2 == 0x75) {
2963 				/* RTS */
2964 #ifdef LOGEMU
2965 				out("rts\n");
2966 #endif
2967 				pc = pop();
2968 			} else if (byte2 == 0x71) {
2969 				/* NOP */
2970 #ifdef LOGEMU
2971 				out("nop");
2972 #endif
2973 			} else if ((byte2 & 0xc0) == 0xc0) {
2974 				/* indir JMP */
2975 #ifdef LOGEMU
2976 				out("jmp");
2977 #endif
2978 				set_info((type8)(byte2 | 0xc0));
2979 				set_arg1();
2980 				if (is_reversible)
2981 					pc = arg1i;
2982 				else
2983 					ms_fatal("illegal addressing mode for JMP");
2984 			} else if ((byte2 & 0xc0) == 0x80) {
2985 #ifdef LOGEMU
2986 				out("jsr");
2987 #endif
2988 				set_info((type8)(byte2 | 0xc0));        /* indir JSR */
2989 				set_arg1();
2990 				push(pc);
2991 				if (is_reversible)
2992 					pc = arg1i;
2993 				else
2994 					ms_fatal("illegal addressing mode for JSR");
2995 			} else {
2996 				ms_fatal("unimplemented instructions 0x4EXX");
2997 			}
2998 		} else
2999 			check_lea();    /* LEA */
3000 		break;
3001 
3002 	/* 50-5F [2ed5] ADDQ/SUBQ/Scc/DBcc */
3003 	case 0x28:
3004 	case 0x29:
3005 	case 0x2a:
3006 	case 0x2b:
3007 	case 0x2c:
3008 	case 0x2d:
3009 	case 0x2e:
3010 	case 0x2f:
3011 
3012 		if ((byte2 & 0xc0) == 0xc0) {
3013 			set_info((type8)(byte2 & 0x3f));
3014 			set_arg1();
3015 			if (admode == 1) {
3016 				/* DBcc */
3017 #ifdef LOGEMU
3018 				out("dbcc");
3019 #endif
3020 				if (condition(byte1) == 0) {
3021 					arg1 = (arg1 - (type8 *) areg) + (type8 *) dreg - 1;
3022 					write_w(arg1, (type16)(read_w(arg1) - 1));
3023 					if (read_w(arg1) != 0xffff)
3024 						branch(0);
3025 					else
3026 						pc += 2;
3027 				} else
3028 					pc += 2;
3029 			} else {
3030 				/* Scc */
3031 #ifdef LOGEMU
3032 				out("scc");
3033 #endif
3034 				arg1[0] = condition(byte1) ? 0xff : 0;
3035 			}
3036 		} else {
3037 			set_info(byte2);
3038 			set_arg1();
3039 			quick_flag = (admode == 1) ? 0xff : 0;
3040 			l1c = byte1 >> 1 & 0x07;
3041 			tmparg[0] = tmparg[1] = tmparg[2] = 0;
3042 			tmparg[3] = l1c ? l1c : 8;
3043 			arg2 = reg_align(tmparg, opsize);
3044 			{
3045 #ifdef LOGEMU
3046 				type32s outnum = 0;
3047 				switch (opsize) {
3048 				case 0:
3049 					outnum = (type8s) arg2[0];
3050 					break;
3051 				case 1:
3052 					outnum = (type16s) read_w(arg2);
3053 					break;
3054 				case 2:
3055 					outnum = (type32s) read_l(arg2);
3056 					break;
3057 				}
3058 #endif
3059 				if ((byte1 & 0x01) == 1) {
3060 #ifdef LOGEMU
3061 					out("subq #%.8X", outnum);
3062 #endif
3063 					do_sub(0);  /* SUBQ */
3064 				} else {
3065 #ifdef LOGEMU
3066 					out("addq #%.8X", outnum);
3067 #endif
3068 					do_add(0);  /* ADDQ */
3069 				}
3070 			}
3071 		}
3072 		break;
3073 
3074 	/* 60-6F [26ba] Bcc */
3075 
3076 	case 0x30:
3077 		if (byte1 == 0x61) {
3078 			/* BRA, BSR */
3079 #ifdef LOGEMU
3080 			out("bsr");
3081 #endif
3082 			if (byte2 == 0)
3083 				push(pc + 2);
3084 			else
3085 				push(pc);
3086 		}
3087 #ifdef LOGEMU
3088 		else
3089 			out("bra");
3090 #endif
3091 		if ((byte1 == 0x60) && (byte2 == 0xfe)) {
3092 			ms_flush(); /* flush stdout */
3093 			ms_stop();  /* infinite loop - just exit */
3094 		}
3095 		branch(byte2);
3096 		break;
3097 
3098 	case 0x31:
3099 	case 0x32:
3100 	case 0x33:
3101 	case 0x34:
3102 	case 0x35:
3103 	case 0x36:
3104 	case 0x37:
3105 
3106 		if (condition(byte1) == 0) {
3107 #ifdef LOGEMU
3108 			out("beq.s");
3109 #endif
3110 			if (byte2 == 0)
3111 				pc += 2;
3112 		} else {
3113 #ifdef LOGEMU
3114 			out("bra");
3115 #endif
3116 			branch(byte2);
3117 		}
3118 		break;
3119 
3120 	/* 70-7F [260a] MOVEQ */
3121 	case 0x38:
3122 	case 0x39:
3123 	case 0x3a:
3124 	case 0x3b:
3125 	case 0x3c:
3126 	case 0x3d:
3127 	case 0x3e:
3128 	case 0x3f:
3129 
3130 #ifdef LOGEMU
3131 		out("moveq");
3132 #endif
3133 		arg1 = (type8 *) & dreg[byte1 >> 1 & 0x07];
3134 		if (byte2 > 127)
3135 			nflag = arg1[0] = arg1[1] = arg1[2] = 0xff;
3136 		else
3137 			nflag = arg1[0] = arg1[1] = arg1[2] = 0;
3138 		arg1[3] = byte2;
3139 		zflag = byte2 ? 0 : 0xff;
3140 		break;
3141 
3142 	/* 80-8F [2f36] */
3143 	case 0x40:
3144 	case 0x41:
3145 	case 0x42:
3146 	case 0x43:
3147 	case 0x44:
3148 	case 0x45:
3149 	case 0x46:
3150 	case 0x47:
3151 
3152 		if ((byte2 & 0xc0) == 0xc0) {
3153 			ms_fatal("unimplemented instructions DIVS and DIVU");
3154 		} else if (((byte2 & 0xf0) == 0) && ((byte1 & 0x01) != 0)) {
3155 			ms_fatal("unimplemented instruction SBCD");
3156 		} else {
3157 #ifdef LOGEMU
3158 			out("or?");
3159 #endif
3160 			set_info(byte2);
3161 			set_arg1();
3162 			set_arg2(1, byte1);
3163 			if ((byte1 & 0x01) == 0)
3164 				swap_args();
3165 			do_or();
3166 		}
3167 		break;
3168 
3169 	/* 90-9F [3005] SUB */
3170 	case 0x48:
3171 	case 0x49:
3172 	case 0x4a:
3173 	case 0x4b:
3174 	case 0x4c:
3175 	case 0x4d:
3176 	case 0x4e:
3177 	case 0x4f:
3178 
3179 #ifdef LOGEMU
3180 		out("sub");
3181 #endif
3182 		quick_flag = 0;
3183 		if ((byte2 & 0xc0) == 0xc0) {
3184 			if ((byte1 & 0x01) == 1)
3185 				set_info((type8)(byte2 & 0xbf));
3186 			else
3187 				set_info((type8)(byte2 & 0x7f));
3188 			set_arg1();
3189 			set_arg2_nosize(0, byte1);
3190 			swap_args();
3191 			do_sub(1);
3192 		} else {
3193 			set_info(byte2);
3194 			set_arg1();
3195 			set_arg2(1, byte1);
3196 			if ((byte1 & 0x01) == 0)
3197 				swap_args();
3198 			do_sub(0);
3199 		}
3200 		break;
3201 
3202 	/* A0-AF various special commands [LINE_A] */
3203 
3204 	case 0x50:
3205 	case 0x56:
3206 	case 0x57:        /* [2521] */
3207 		do_line_a();
3208 #ifdef LOGEMU
3209 		out("LINE_A A0%.2X", byte2);
3210 #endif
3211 		break;
3212 
3213 	case 0x51:
3214 #ifdef LOGEMU
3215 		out("rts\n");
3216 #endif
3217 		pc = pop(); /* RTS */
3218 		break;
3219 
3220 	case 0x52:
3221 #ifdef LOGEMU
3222 		out("bsr");
3223 #endif
3224 		if (byte2 == 0)
3225 			push(pc + 2);   /* BSR */
3226 		else
3227 			push(pc);
3228 		branch(byte2);
3229 		break;
3230 
3231 	case 0x53:
3232 		if ((byte2 & 0xc0) == 0xc0) {
3233 			/* TST [321d] */
3234 			ms_fatal("unimplemented instructions LINE_A #$6C0-#$6FF");
3235 		} else {
3236 #ifdef LOGEMU
3237 			out("tst");
3238 #endif
3239 			set_info(byte2);
3240 			set_arg1();
3241 			cflag = vflag = 0;
3242 			set_flags();
3243 		}
3244 		break;
3245 
3246 	case 0x54:
3247 		check_movem();
3248 		break;
3249 
3250 	case 0x55:
3251 		check_movem2();
3252 		break;
3253 
3254 	/* B0-BF [2fe4] */
3255 	case 0x58:
3256 	case 0x59:
3257 	case 0x5a:
3258 	case 0x5b:
3259 	case 0x5c:
3260 	case 0x5d:
3261 	case 0x5e:
3262 	case 0x5f:
3263 
3264 		if ((byte2 & 0xc0) == 0xc0) {
3265 #ifdef LOGEMU
3266 			out("cmp");
3267 #endif
3268 			if ((byte1 & 0x01) == 1)
3269 				set_info((type8)(byte2 & 0xbf));
3270 			else
3271 				set_info((type8)(byte2 & 0x7f));
3272 			set_arg1();
3273 			set_arg2(0, byte1);
3274 			swap_args();
3275 			do_cmp();   /* CMP */
3276 		} else {
3277 			if ((byte1 & 0x01) == 0) {
3278 #ifdef LOGEMU
3279 				out("cmp");
3280 #endif
3281 				set_info(byte2);
3282 				set_arg1();
3283 				set_arg2(1, byte1);
3284 				swap_args();
3285 				do_cmp();   /* CMP */
3286 			} else {
3287 #ifdef LOGEMU
3288 				out("eor");
3289 #endif
3290 				set_info(byte2);
3291 				set_arg1();
3292 				set_arg2(1, byte1);
3293 				do_eor();   /* EOR */
3294 			}
3295 		}
3296 		break;
3297 
3298 	/* C0-CF [2f52] EXG, AND */
3299 	case 0x60:
3300 	case 0x61:
3301 	case 0x62:
3302 	case 0x63:
3303 	case 0x64:
3304 	case 0x65:
3305 	case 0x66:
3306 	case 0x67:
3307 
3308 		if ((byte1 & 0x01) == 0) {
3309 			if ((byte2 & 0xc0) == 0xc0) {
3310 				ms_fatal("unimplemented instruction MULU");
3311 			} else {
3312 				/* AND */
3313 #ifdef LOGEMU
3314 				out("and");
3315 #endif
3316 				set_info(byte2);
3317 				set_arg1();
3318 				set_arg2(1, byte1);
3319 				if ((byte1 & 0x01) == 0)
3320 					swap_args();
3321 				do_and();
3322 			}
3323 		} else {
3324 			if ((byte2 & 0xf8) == 0x40) {
3325 #ifdef LOGEMU
3326 				out("exg (dx)");
3327 #endif
3328 				opsize = 2; /* EXG Dx,Dx */
3329 				set_arg2(1, (type8)(byte2 << 1));
3330 				swap_args();
3331 				set_arg2(1, byte1);
3332 				tmp32 = read_l(arg1);
3333 				write_l(arg1, read_l(arg2));
3334 				write_l(arg2, tmp32);
3335 			} else if ((byte2 & 0xf8) == 0x48) {
3336 				opsize = 2; /* EXG Ax,Ax */
3337 #ifdef LOGEMU
3338 				out("exg (ax)");
3339 #endif
3340 				set_arg2(0, (type8)(byte2 << 1));
3341 				swap_args();
3342 				set_arg2(0, byte1);
3343 				tmp32 = read_l(arg1);
3344 				write_l(arg1, read_l(arg2));
3345 				write_l(arg2, tmp32);
3346 			} else if ((byte2 & 0xf8) == 0x88) {
3347 				opsize = 2; /* EXG Dx,Ax */
3348 #ifdef LOGEMU
3349 				out("exg (dx,ax)");
3350 #endif
3351 				set_arg2(0, (type8)(byte2 << 1));
3352 				swap_args();
3353 				set_arg2(1, byte1);
3354 				tmp32 = read_l(arg1);
3355 				write_l(arg1, read_l(arg2));
3356 				write_l(arg2, tmp32);
3357 			} else {
3358 				if ((byte2 & 0xc0) == 0xc0) {
3359 					ms_fatal("unimplemented instruction MULS");
3360 				} else {
3361 					set_info(byte2);
3362 					set_arg1();
3363 					set_arg2(1, byte1);
3364 					if ((byte1 & 0x01) == 0)
3365 						swap_args();
3366 					do_and();
3367 				}
3368 			}
3369 		}
3370 		break;
3371 
3372 	/* D0-DF [2fc8] ADD */
3373 	case 0x68:
3374 	case 0x69:
3375 	case 0x6a:
3376 	case 0x6b:
3377 	case 0x6c:
3378 	case 0x6d:
3379 	case 0x6e:
3380 	case 0x6f:
3381 
3382 #ifdef LOGEMU
3383 		out("add");
3384 #endif
3385 		quick_flag = 0;
3386 		if ((byte2 & 0xc0) == 0xc0) {
3387 			if ((byte1 & 0x01) == 1)
3388 				set_info((type8)(byte2 & 0xbf));
3389 			else
3390 				set_info((type8)(byte2 & 0x7f));
3391 			set_arg1();
3392 			set_arg2_nosize(0, byte1);
3393 			swap_args();
3394 			do_add(1);
3395 		} else {
3396 			set_info(byte2);
3397 			set_arg1();
3398 			set_arg2(1, byte1);
3399 			if ((byte1 & 0x01) == 0)
3400 				swap_args();
3401 			do_add(0);
3402 		}
3403 		break;
3404 
3405 	/* E0-EF [3479] LSR ASL ROR ROL */
3406 	case 0x70:
3407 	case 0x71:
3408 	case 0x72:
3409 	case 0x73:
3410 	case 0x74:
3411 	case 0x75:
3412 	case 0x76:
3413 	case 0x77:
3414 
3415 #ifdef LOGEMU
3416 		out("lsr,asl,ror,rol");
3417 #endif
3418 		if ((byte2 & 0xc0) == 0xc0) {
3419 			set_info((type8)(byte2 & 0xbf));        /* OP Dx */
3420 			set_arg1();
3421 			l1c = 1;    /* steps=1 */
3422 			byte2 = (byte1 >> 1) & 0x03;
3423 		} else {
3424 			set_info((type8)(byte2 & 0xc7));
3425 			set_arg1();
3426 			if ((byte2 & 0x20) == 0) {
3427 				/* immediate */
3428 				l1c = (byte1 >> 1) & 0x07;
3429 				if (l1c == 0)
3430 					l1c = 8;
3431 			} else {
3432 				l1c = (type8)read_reg(byte1 >> 1 & 0x07, 0);
3433 			}
3434 			byte2 = (byte2 >> 3) & 0x03;
3435 		}
3436 		if ((byte1 & 0x01) == 0) {
3437 			/* right */
3438 			while (l1c-- > 0) {
3439 				if (opsize == 0) {
3440 					cflag = arg1[0] & 0x01 ? 0xff : 0;
3441 					arg1[0] >>= 1;
3442 					if (cflag && (byte2 == 3))
3443 						arg1[0] |= 0x80;
3444 				}
3445 				if (opsize == 1) {
3446 					cflag = read_w(arg1) & 0x01 ? 0xff : 0;
3447 					write_w(arg1, (type16)(read_w(arg1) >> 1));
3448 					if (cflag && (byte2 == 3))
3449 						write_w(arg1, (type16)(read_w(arg1) | ((type16) 1 << 15)));
3450 				}
3451 				if (opsize == 2) {
3452 					cflag = read_l(arg1) & 0x01 ? 0xff : 0;
3453 					write_l(arg1, read_l(arg1) >> 1);
3454 					if (cflag && (byte2 == 3))
3455 						write_l(arg1, read_l(arg1) | ((type32) 1 << 31));
3456 				}
3457 			}
3458 		} else {
3459 			/* left */
3460 			while (l1c-- > 0) {
3461 				if (opsize == 0) {
3462 					cflag = arg1[0] & 0x80 ? 0xff : 0;  /* [3527] */
3463 					arg1[0] <<= 1;
3464 					if (cflag && (byte2 == 3))
3465 						arg1[0] |= 0x01;
3466 				}
3467 				if (opsize == 1) {
3468 					cflag = read_w(arg1) & ((type16) 1 << 15) ? 0xff : 0;
3469 					write_w(arg1, (type16)(read_w(arg1) << 1));
3470 					if (cflag && (byte2 == 3))
3471 						write_w(arg1, (type16)(read_w(arg1) | 0x01));
3472 				}
3473 				if (opsize == 2) {
3474 					cflag = read_l(arg1) & ((type32) 1 << 31) ? 0xff : 0;
3475 					write_l(arg1, read_l(arg1) << 1);
3476 					if (cflag && (byte2 == 3))
3477 						write_l(arg1, read_l(arg1) | 0x01);
3478 				}
3479 			}
3480 		}
3481 		set_flags();
3482 		break;
3483 
3484 	/* F0-FF [24f3] LINE_F */
3485 	case 0x78:
3486 	case 0x79:
3487 	case 0x7a:
3488 	case 0x7b:
3489 	case 0x7c:
3490 	case 0x7d:
3491 	case 0x7e:
3492 	case 0x7f:
3493 
3494 		if (version == 0) {
3495 			/* hardcoded jump */
3496 			char_out(l1c = (type8)read_reg(1, 0));
3497 		} else if (version == 1) {
3498 			/* single programmable shortcut */
3499 			push(pc);
3500 			pc = fl_sub;
3501 		} else {
3502 			/* programmable shortcuts from table */
3503 #ifdef LOGEMU
3504 			out("LINK: %.2X,%.2X", byte1, byte2);
3505 #endif
3506 			ptr = (byte1 & 7) << 8 | byte2;
3507 			if (ptr >= fl_size) {
3508 				if ((byte1 & 8) == 0)
3509 					push(pc);
3510 				ptr = byte1 << 8 | byte2 | 0x0800;
3511 				ptr = fl_tab + 2 * (ptr ^ 0xffff);
3512 				pc = (type32) ptr + (type16s) read_w(effective(ptr));
3513 			} else {
3514 				push(pc);
3515 				pc = fl_sub;
3516 			}
3517 		}
3518 		break;
3519 
3520 	default:
3521 		ms_fatal("Constants aren't and variables don't");
3522 		break;
3523 	}
3524 #ifdef LOGEMU
3525 	fprintf(dbg_log, "\n");
3526 #endif
3527 	return running;
3528 }
3529 
3530 } // End of namespace Magnetic
3531 } // End of namespace Glk
3532